package cn.hengzhu.main_manager.service.impl;

import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;

import cn.hengzhu.main_manager.repository.dao.*;
import cn.hengzhu.main_manager.repository.domain.*;
import cn.hengzhu.main_manager.repository.vo.*;
import cn.hengzhu.main_manager.service.PayOrderService;
import cn.hengzhu.main_manager.utils.*;
import cn.hengzhu.main_manager.web.xcx.WXXcxCommonContrller;
//import com.sun.org.apache.bcel.internal.generic.NEW;
import org.apache.commons.lang3.StringUtils;
//import org.apache.ibatis.ognl.ASTList;
import org.apache.log4j.Logger;
//import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import cn.hengzhu.main_manager.repository.param.UpdateUserLoginParam;
import cn.hengzhu.main_manager.service.ManageCaseBoxService;
import cn.hengzhu.main_manager.service.SysConstService;
import cn.hengzhu.main_manager.utils.config.AllConst;
import cn.hengzhu.main_manager.utils.config.xcx.WxConfig;

@Service
@Transactional(rollbackFor = Exception.class)
public class ManageCaseBoxServiceImpl implements ManageCaseBoxService {
	private Logger log = Logger.getLogger(ManageCaseBoxServiceImpl.class);
	@Autowired
	private ManageCaseBoxMapper manageCaseBoxMapper;
	@Autowired
	private ManageCaseMapper manageCaseMapper;
	@Autowired
	private AccessRecordMapper accessRecordMapper;
	@Autowired
	private ManageUserMapper manageUserMapper;
	@Autowired
	private ManageRolesMapper manageRolesMapper;
	@Autowired
	private ManageCompMapper manageCompMapper;
	@Autowired
	private ManageCaseTypeMapper manageCaseTypeMapper;
	@Autowired
	private PayOrderMapper payOrderMapper;
	@Autowired
	private CustomersAmountMapper customersAmountMapper;
	@Autowired
	private CustomersRefundMapper customersRefundMapper;
	@Autowired
	private PrepayOrderMapper prepayOrderMapper;
	@Autowired
	private MobileKeyMapper mobileKeyMapper;
	@Autowired
	private SysConstMapper sysConstMapper;
	@Autowired
	private SysConstService sysConstService;
	@Autowired
	private ManageCaseTypePriceMapper manageCaseTypePriceMapper;
	@Autowired
	private PayOrderService payOrderService;


	@Override
	public void boxClear(ManageCaseBox manageCaseBox, ManageCase manageCase) throws Exception {

		Date date = new Date();
		ManageUser user = UserContext.getUser();
		String loginName = user.getLoginName();

		Integer boxId = manageCaseBox.getId();
		Byte saveSource = manageCaseBox.getSaveSource();
		Byte useType = manageCase.getUseType();
		if (Byte.valueOf("3").equals(useType)) {

			String dateStr = DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd");
			// 清除储物柜状态
			ManageCaseBox updateRecord = new ManageCaseBox();
			ManageCaseBoxExample updateExample = new ManageCaseBoxExample();
			updateRecord.setUseStatus((byte) 0);
			updateExample.createCriteria().andIdEqualTo(boxId);
			int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(updateRecord, updateExample);
			// 插入清除记录
			AccessRecord accessRecord = new AccessRecord();
			accessRecord.setSource((byte) 1);
			accessRecord.setCreateTime(date);
			accessRecord.setType((byte) 3);
			accessRecord.setUserId(loginName);
			accessRecord.setCreateDay(dateStr);
			accessRecord.setBoxId(boxId);
			int insertBatchByExpress = accessRecordMapper.insertSelective(accessRecord);

			// 修改短信的状态码
			MobileKey updateMobileKeyRecord = new MobileKey();
			MobileKeyExample updateMobileKeyExample = new MobileKeyExample();
			updateMobileKeyRecord.setStatus((byte) 2);
			updateMobileKeyExample.createCriteria().andStatusEqualTo((byte) 1).andBoxIdEqualTo(boxId);
			int updateByExampleSelective2 = mobileKeyMapper.updateByExampleSelective(updateMobileKeyRecord,
					updateMobileKeyExample);
			if (updateByExampleSelective == 0 || insertBatchByExpress == 0 || updateByExampleSelective2 == 0) {
				throw new Exception();
			}
		} else {
			if (saveSource.equals(AllConst.CASE_BOX_SAVE_SOURCE.ALI_XCX_SAVE_SOURCE)
					|| saveSource.equals(AllConst.CASE_BOX_SAVE_SOURCE.WX_XCX_SAVE_SOURCE)) {
				// 来自于微信小程序，支付宝小程序
				// 需要在余额中结算费用
				// 1.查询储物柜
				Integer typeId = manageCase.getTypeId();
				// 查询收费类型
				ManageCaseType manageCaseType = manageCaseTypeMapper.selectByPrimaryKey(typeId);

				double amount = CustomersAmountCount.getAliCharge(manageCaseBox, manageCase, manageCaseType); // 费用
				if (amount > 0) {// 大于0,修改账户余额
					// 查询账户余额
					amount = amount > 100 ? 100 : amount;
					CustomersAmountExample amountExample = new CustomersAmountExample();
					amountExample.createCriteria().andOpenIdEqualTo(manageCaseBox.getUserId());
					List<CustomersAmount> selectByExample2 = customersAmountMapper.selectByExample(amountExample);
					if(selectByExample2 != null && !selectByExample2.isEmpty()){
						CustomersAmount customersAmount = selectByExample2.get(0);
						Integer amountId = customersAmount.getAmountId();
						double totalAmount = customersAmount.getTotalAmount().doubleValue(); // 账户余额
						double newtotalAmount = totalAmount - amount;
						Byte source = customersAmount.getSource();
						// 修改账户余额
						CustomersAmount record = new CustomersAmount();
						record.setTotalAmount(BigDecimal.valueOf(newtotalAmount));
						record.setAmountId(amountId);
						customersAmountMapper.updateByPrimaryKeySelective(record);

						// 插入使用记录
						AccessRecord accessRecord = new AccessRecord();
						if (Byte.valueOf("2").equals(source)) {// 2，微信小程序 3.支付宝小程序''
							accessRecord.setSource((byte) 3);
						} else if (Byte.valueOf("3").equals(source)) {// 2，微信小程序
																		// 3.支付宝小程序''
							accessRecord.setSource((byte) 5);
						}
						accessRecord.setBoxId(boxId);
						accessRecord.setCreateTime(date);
						accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.PASSIVITY_CLEAR_TYEP);
						accessRecord.setUserId(manageCaseBox.getUserId());
						accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
						accessRecord.setCharge(BigDecimal.valueOf(0 - amount));
						accessRecordMapper.insertSelective(accessRecord);
					}

				}
			}
			// 清空储物箱状态
			ManageCaseBox caseBoxRecord = new ManageCaseBox();
			caseBoxRecord.setId(boxId);
			caseBoxRecord.setUseStatus((byte) 0);
			manageCaseBoxMapper.updateByPrimaryKeySelective(caseBoxRecord);
			// 插入一条清除记录
			AccessRecord accessRecord = new AccessRecord();
			accessRecord.setSource((byte) 1);
			accessRecord.setBoxId(boxId);
			accessRecord.setCreateTime(date);
			accessRecord.setType((byte) 3);
			accessRecord.setUserId(loginName);
			accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
			accessRecordMapper.insertSelective(accessRecord);
		}
	}



	/**
	 * caseNO mac地址
	 * boxNum 门号
	 * loginName 登录用户名称
	 * 开箱记录
	 */
	@Override
	public void addRecorByAdmin(String caseNo, Integer boxNum, String loginName) {
		Date date = new Date();
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andCaseNoEqualTo(caseNo).andDoorNumEqualTo(boxNum).andIsDelEqualTo((byte) 0); //CASE_NO = caseNo and DOOR_NUM = boxNum and IS_DEL = 0
		List<ManageCaseBox> selectByExample = manageCaseBoxMapper.selectByExample(example);
		ManageCaseBox boxByBoxNum = selectByExample.get(0);

		Integer id = boxByBoxNum.getId();
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setCreateTime(date);
		accessRecord.setSource((byte) 1);
		accessRecord.setType((byte) 4);
		accessRecord.setUserId(loginName);
		accessRecord.setBoxId(id);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecordMapper.insertSelective(accessRecord);
	}

	@Override
	public OpenBoxListVO getBoxList(String caseNo, String fromUserName) {
		OpenBoxListVO openBoxListVO = new OpenBoxListVO();
		List<BoxListVO> list = new ArrayList<>();
		// 查询储物柜的基本信息
		ManageCaseExample caseExample = new ManageCaseExample();
		caseExample.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> selectByExample3 = manageCaseMapper.selectByExample(caseExample);

		if (!selectByExample3.isEmpty()) {
			ManageCase manageCase = selectByExample3.get(0);
			Integer compId = manageCase.getCompId();

			Date date = new Date();
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			// 八小时前
			calendar.add(Calendar.HOUR_OF_DAY, -8);
			Date time = calendar.getTime();

			// 查询是否已经使用了这个储物柜
			ManageCaseBoxExample example = new ManageCaseBoxExample();
			example.createCriteria().andCaseNoEqualTo(caseNo).andUserIdEqualTo(fromUserName)
					.andUseStatusEqualTo((byte) 1).andIsDelEqualTo((byte) 0);
			List<ManageCaseBox> selectByExample = manageCaseBoxMapper.selectByExample(example);

			// 查询是否为本公司的管理员
			ManageUserExample userExample = new ManageUserExample();
			userExample.createCriteria().andFormUserNameEqualTo(fromUserName).andCompIdEqualTo(compId);
			List<ManageUser> manageUserList = manageUserMapper.selectByExample(userExample);

			// 如果不为空，，，表示是此公司的管理员，就可以直接返回全部的储物柜
			if (!manageUserList.isEmpty()) {
				// 是他们公司的，，，那就可以开全部，，，全部返给他
				ManageCaseBoxExample caseBoxexample = new ManageCaseBoxExample();
				caseBoxexample.createCriteria().andCaseNoEqualTo(caseNo).andIsDelEqualTo((byte) 0);
				List<ManageCaseBox> boxList = manageCaseBoxMapper.selectByExample(caseBoxexample);
				boxList.stream().forEach(a -> {
					BoxListVO boxListVO = new BoxListVO();
					boxListVO.setBoxNum(a.getDoorNum());
					boxListVO.setCaseNo(caseNo);
					boxListVO.setFlag((byte) 0);
					if (Byte.valueOf("1").equals(a.getUseStatus())) {
						long time2 = a.getSaveTime().getTime();
						long time3 = time.getTime();
						if (time2 < time3) {
							boxListVO.setSign((byte) 2);
						} else {
							boxListVO.setSign((byte) 1);
						}
					}
					openBoxListVO.setAdminFlag((byte) 1);
					list.add(boxListVO);
				});

			} else {// 不是本公司的管理员，，，，纯粹的客户
					// 判断存或 取
				if (!selectByExample.isEmpty()) {// 取物
					ManageCaseBox manageCaseBox = selectByExample.get(0);
					BoxListVO boxListVO = new BoxListVO();
					boxListVO.setBoxNum(manageCaseBox.getDoorNum());
					boxListVO.setCaseNo(caseNo);
					list.add(boxListVO);

				} else {// 存物
					ManageCaseBoxExample caseBoxexample = new ManageCaseBoxExample();
					caseBoxexample.createCriteria().andCaseNoEqualTo(caseNo).andIsDelEqualTo((byte) 0)
							.andUseStatusEqualTo((byte) 0);
					List<ManageCaseBox> boxList = manageCaseBoxMapper.selectByExample(caseBoxexample);
					boxList.stream().forEach(a -> {
						BoxListVO boxListVO = new BoxListVO();
						Byte switchStatus = a.getSwitchStatus();
						Byte useStatus = a.getUseStatus();
						boxListVO.setBoxNum(a.getDoorNum());
						boxListVO.setCaseNo(caseNo);
						if (Byte.valueOf("1").equals(switchStatus) && Byte.valueOf("0").equals(useStatus)) {
							boxListVO.setFlag((byte) 0);
						} else {
							boxListVO.setFlag((byte) 1);
						}
						list.add(boxListVO);
					});
				}
			}
		}
		openBoxListVO.setList(list);
		return openBoxListVO;
	}

	@Override
	public Map<String, String> getOpenDoor(String fromUserName, String caseNo, Integer boxNum) throws Exception {
		boolean isSend = false;
		Map<String, String> map = new HashMap<>();
		// 1.查询储物柜属于哪个公司
		Date date = new Date();
		ManageCaseExample example = new ManageCaseExample();
		example.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> selectByExample2 = manageCaseMapper.selectByExample(example);
		ManageCase manageCase = selectByExample2.get(0);
		Integer compId = manageCase.getCompId();

		// 2.查询此人是否为本储物柜所属公司的管理员
		ManageUserExample userExample = new ManageUserExample();
		userExample.createCriteria().andFormUserNameEqualTo(fromUserName).andCompIdEqualTo(compId);
		List<ManageUser> manageUserList = manageUserMapper.selectByExample(userExample);

		if (!manageUserList.isEmpty()) {// 不为空则是管理员（可以开全部）
			ManageCaseBoxExample boxExample = new ManageCaseBoxExample();
			boxExample.createCriteria().andCaseNoEqualTo(caseNo).andDoorNumEqualTo(boxNum).andIsDelEqualTo((byte) 0);
			List<ManageCaseBox> selectByExample = manageCaseBoxMapper.selectByExample(boxExample);
			ManageCaseBox boxByBoxNum = selectByExample.get(0);
			// 插入开箱记录
			AccessRecord accessRecord = new AccessRecord();
			accessRecord.setBoxId(boxByBoxNum.getId());
			accessRecord.setCreateTime(date);
			accessRecord.setSource((byte) 1);
			accessRecord.setType((byte) 4);
			accessRecord.setUserId(fromUserName);
			accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
			try {
				accessRecordMapper.insertSelective(accessRecord);
				isSend = true;
				map.put("message", boxNum + "号开箱成功");
				map.put("flag", "4");
			} catch (Exception e) {
				map.put("message", boxNum + "号开箱失败,请重试");
				map.put("flag", "3");
			}
		} else {// 其他的都是用户

			// 查询是否已经使用了
			ManageCaseBoxExample example11 = new ManageCaseBoxExample();
			example11.createCriteria().andUseStatusEqualTo((byte) 1).andIsDelEqualTo((byte) 0)
					.andUserIdEqualTo(fromUserName).andCaseNoEqualTo(caseNo).andDoorNumEqualTo(boxNum);
			List<ManageCaseBox> isUser = manageCaseBoxMapper.selectByExample(example11);

			ManageCaseBoxExample boxExample = new ManageCaseBoxExample();
			boxExample.createCriteria().andCaseNoEqualTo(caseNo).andDoorNumEqualTo(boxNum).andIsDelEqualTo((byte) 0);
			List<ManageCaseBox> selectByExample = manageCaseBoxMapper.selectByExample(boxExample);
			ManageCaseBox boxByBoxNum = selectByExample.get(0);
			Byte useStatus = boxByBoxNum.getUseStatus();
			Byte switchStatus = boxByBoxNum.getSwitchStatus();

			if (Byte.valueOf("0").equals(useStatus) && Byte.valueOf("1").equals(switchStatus)) {// 空闲
				if (!isUser.isEmpty()) {// 已使用
					map.put("message", "开箱失败，一次只能使用一个箱子");
					map.put("flag", "3");
				} else {
					AccessRecord accessRecord = new AccessRecord();
					accessRecord.setBoxId(boxByBoxNum.getId());
					accessRecord.setCreateTime(date);
					accessRecord.setSource((byte) 2);
					accessRecord.setType((byte) 1);
					accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
					accessRecord.setUserId(fromUserName);
					//
					ManageCaseBox manageCaseBox = new ManageCaseBox();
					manageCaseBox.setSaveTime(date);
					manageCaseBox.setUserId(fromUserName);
					manageCaseBox.setUseStatus((byte) 1);
					manageCaseBox.setSaveSource((byte) 1);
					manageCaseBox.setVersion(boxByBoxNum.getVersion() + 1);

					ManageCaseBoxExample caseBoxexample = new ManageCaseBoxExample();
					caseBoxexample.createCriteria().andIdEqualTo(boxByBoxNum.getId())
							.andVersionEqualTo(boxByBoxNum.getVersion());

					try {
						accessRecordMapper.insertSelective(accessRecord);
						int updateStatus = manageCaseBoxMapper.updateByExampleSelective(manageCaseBox, caseBoxexample);
						if (updateStatus == 0) {
							map.put("message", boxNum + "号开箱失败,请重试");
							map.put("flag", "3");
						} else {
							isSend = true;
							map.put("message", "开箱成功，请存入" + boxNum + "号箱中");
							map.put("flag", "1");
						}
					} catch (Exception e) {
						map.put("message", boxNum + "号开箱失败,请重试");
						map.put("flag", "3");
					}
				}
			} else if (Byte.valueOf("1").equals(useStatus) && Byte.valueOf("1").equals(switchStatus)) {// 占用
				String userId = boxByBoxNum.getUserId();
				if (StringUtils.isNotBlank(userId) && userId.equals(fromUserName)) {
					// 插入开箱记录
					AccessRecord accessRecord = new AccessRecord();
					accessRecord.setBoxId(boxByBoxNum.getId());
					accessRecord.setCreateTime(date);
					accessRecord.setSource((byte) 2);
					accessRecord.setType((byte) 2);
					accessRecord.setUserId(fromUserName);
					accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
					// 修改箱子的状态和储物人
					ManageCaseBox manageCaseBox = new ManageCaseBox();
					manageCaseBox.setUseStatus((byte) 0);
					manageCaseBox.setVersion(boxByBoxNum.getVersion() + 1);
					ManageCaseBoxExample caseBoxexample = new ManageCaseBoxExample();
					caseBoxexample.createCriteria().andIdEqualTo(boxByBoxNum.getId())
							.andVersionEqualTo(boxByBoxNum.getVersion());
					try {
						accessRecordMapper.insertSelective(accessRecord);
						int updateStatus = manageCaseBoxMapper.updateByExampleSelective(manageCaseBox, caseBoxexample);
						if (updateStatus == 0) {
							map.put("message", boxNum + "号开箱失败,请重试");
							map.put("flag", "3");
						} else {
							isSend = true;
							map.put("message", boxNum + "号开箱成功，请取出物品，并关闭箱门");
							map.put("flag", "2");
						}
					} catch (Exception e) {
						map.put("message", boxNum + "号开箱失败,请重试");
						map.put("flag", "3");
					}

				} else {
					map.put("message", "已被抢走或已被管理员关闭，请重新选择");
					map.put("flag", "3");
				}
			}

		}
		if (isSend) {
			Connection connection = ConnectionUtils.getConnection();
			Channel channel = connection.createChannel();
			Map<String, Object> args = new HashMap<String, Object>();
			args.put("x-message-ttl", 40000);
			channel.queueDeclare(caseNo, true, false, false, args);
			Map<String, Object> sendMap = new HashMap<>();
			sendMap.put("door", boxNum);
			sendMap.put("timestamp", date.getTime());
			ObjectMapper mapper = new ObjectMapper();
			String writeValueAsString = mapper.writeValueAsString(sendMap);
			channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
			channel.close();
			connection.close();
		}
		return map;
	}

	/**
	 * @author 刘成
	 * @since 2018年7月2日
	 * @param caseNo
	 * @param fromUserName
	 * @return 一键开箱操作
	 * @throws TimeoutException
	 * @throws IOException
	 * @throws InterruptedException
	 */
	@Override
	public Map<String, String> oneKeyOpen(String caseNo, String fromUserName) throws Exception {
		Map<String, String> map = new HashMap<>();
		ManageCaseBoxExample caseBoxexample = new ManageCaseBoxExample();
		caseBoxexample.createCriteria().andCaseNoEqualTo(caseNo).andIsDelEqualTo((byte) 0);
		List<ManageCaseBox> boxListByCaseNo = manageCaseBoxMapper.selectByExample(caseBoxexample);
		Map<Integer, ManageCaseBox> boxMap = boxListByCaseNo.stream()
				.collect(Collectors.toMap(ManageCaseBox::getDoorNum, a -> a));
		if (!boxListByCaseNo.isEmpty()) {
			int size = boxListByCaseNo.size();
			Date date = new Date();
			Connection connection = ConnectionUtils.getConnection();
			Channel channel = connection.createChannel();
			Map<String, Object> sendMap = new HashMap<>();
			for (int i = 0; i < size; i++) {
				if (i > 0) {
					Thread.sleep(500l);
				}
				AccessRecord accessRecord = new AccessRecord();
				accessRecord.setCreateTime(date);
				accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
				accessRecord.setBoxId(boxMap.get(i + 1).getId());
				accessRecord.setSource((byte) 1);
				accessRecord.setType((byte) 5);
				accessRecord.setUserId(fromUserName);
				accessRecordMapper.insertSelective(accessRecord);
				// 发送消息
				sendMap.put("door", i + 1);
				sendMap.put("timestamp", date.getTime());
				ObjectMapper mapper = new ObjectMapper();
				Map<String, Object> args = new HashMap<String, Object>();
				args.put("x-message-ttl", 40000);
				channel.queueDeclare(caseNo, true, false, false, args);
				String writeValueAsString = mapper.writeValueAsString(sendMap);
				channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
			}
			channel.close();
			connection.close();
			map.put("message", "一键开箱成功");
		}
		return map;
	}

	@Override
	public void boxClearByWX(Integer boxId, String fromUserName) {
		Date date = new Date();
		// 清空储物箱状态
		ManageCaseBox record = new ManageCaseBox();
		record.setId(boxId);
		record.setUseStatus((byte) 0);
		manageCaseBoxMapper.updateByPrimaryKeySelective(record);
		// 插入一条清除记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setSource((byte) 1);
		accessRecord.setBoxId(boxId);
		accessRecord.setCreateTime(date);
		accessRecord.setType((byte) 3);
		accessRecord.setUserId(fromUserName);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecordMapper.insertSelective(accessRecord);

	}

	/**
	 * @author 刘成
	 * @since 2018年7月9日
	 * @param manageRoles
	 *            修改角色时，清除绑定的微信账号
	 */
	public void clearBind(ManageRoles manageRoles) {

		manageRolesMapper.updateByPrimaryKeySelective(manageRoles);
		Integer roleId = manageRoles.getRoleId();
		ManageUserExample example = new ManageUserExample();
		example.createCriteria().andRoleIdEqualTo(roleId);
		List<ManageUser> userByRoleId = manageUserMapper.selectByExample(example);
		if (!userByRoleId.isEmpty()) {
			List<Integer> managerIds = userByRoleId.stream()
					.collect(Collectors.mapping(ManageUser::getManagerId, Collectors.toList()));
			for (Integer managerId : managerIds) {
				ManageUser record = new ManageUser();
				record.setManagerId(managerId);
				record.setFormUserName(null);
				manageUserMapper.updateByPrimaryKeySelective(record);
			}
		}
	}

	@Override
	public void clearBindByUpadateManager(UpdateUserLoginParam param) {
		manageUserMapper.updateInfoByManager(param);
		Integer managerId = param.getManagerId();
		ManageUser record = new ManageUser();
		record.setManagerId(managerId);
		record.setFormUserName(null);
		manageUserMapper.updateByPrimaryKeySelective(record);
	}

	/**
	 * @author 刘成
	 * @since 2018年8月14日 添加公司的一系列操作
	 */
	@Override
	public void addComp(ManageComp param) {

		manageCompMapper.insertSelective(param);
		Integer compId2 = param.getCompId();
		// 添加公司后还需要为公司添加一条免费的收费类型
		ManageCaseType record = new ManageCaseType();
		record.setCrateTime(new Date());
		record.setName("免费");
		record.setCompId(compId2);
		record.setIsDefault((byte) 1);
		manageCaseTypeMapper.insertSelective(record);

	}

	@Override
	public void setDefaultType(Integer typeId2, ManageCaseType manageCaseType) throws Exception {
		ManageCaseType record = new ManageCaseType();
		record.setIsDefault((byte) 0);
		record.setTypeId(typeId2);
		manageCaseTypeMapper.updateByPrimaryKeySelective(record);
		manageCaseTypeMapper.updateByPrimaryKeySelective(manageCaseType);
	}


	/**
	 * 微信充值回调
	 * @param map
	 * @throws Exception
	 */
	@Override
	public void payBack(Map<String, String> map) throws Exception {

		String outTradeNo = map.get("out_trade_no"); // 交易编号
		String bankType = map.get("bank_type"); // 支付方式
		String openId = map.get("openid");
		// 金额
		String totalFee = map.get("total_fee");
		double valueOf = Double.valueOf(totalFee);

		String transactionId = map.get("transaction_id");
		PayOrderExample payexample = new PayOrderExample();
		// IS_PAY = 0 未支付的
		payexample.createCriteria().andOutTradeNoEqualTo(outTradeNo).andIsPayEqualTo((byte) 0) //OUT_TRADE_NO = outTradeNo and  IS_PAY = 0 and TOTAL_FEE = totalFee
				.andTotalFeeEqualTo(Integer.valueOf(totalFee));

		List<PayOrder> payOrderList = payOrderMapper.selectByExample(payexample); // 查询出此订单信息
		if (!payOrderList.isEmpty()) {// 不为空则代表有此条订单消息
			PayOrder payOrder = payOrderList.get(0);
			Integer orderId = payOrder.getOrderId(); // 交易订单主键
			// 修改记录
			PayOrder record = new PayOrder();
			record.setBankType(bankType); // 支付方式
			record.setIsPay((byte) 1); // 改为已支付
			record.setTransactionId(transactionId); // 支付订单号
			record.setOrderId(orderId);
			// 修改订单为处理状态 pay_order
			payOrderMapper.updateByPrimaryKeySelective(record);

			// 根据订单号处理相应的业务
			String bizOrder = outTradeNo.substring(0, 2); // cz 代表充值

			CustomersAmount customersAmountrecord = new CustomersAmount();
			CustomersAmountExample example = new CustomersAmountExample();
			example.createCriteria().andOpenIdEqualTo(openId);
			List<CustomersAmount> selectByExample = customersAmountMapper.selectByExample(example);
			// 查询得到用户的账户
			CustomersAmount customersAmount = selectByExample.get(0);
			// 账户Id 主键
			Integer amountId = customersAmount.getAmountId();
			if (bizOrder.equals("cz")) {// 充值
				// 账户余额
				BigDecimal totalAmount = customersAmount.getTotalAmount();
				double doubleValue = totalAmount.doubleValue();
				double tot = doubleValue + valueOf / 100; // 之前的余额 加上现在充值的余额
				customersAmountrecord.setAmountId(amountId);
				customersAmountrecord.setTotalAmount(BigDecimal.valueOf(tot));
				customersAmountMapper.updateByPrimaryKeySelective(customersAmountrecord); // 修改用户余额

			} else if (bizOrder.equals("yj")) {// 缴纳押金
				customersAmountrecord.setAssureAmount(BigDecimal.valueOf(valueOf / 100));
				customersAmountrecord.setIsPay((byte) 1); // '是否缴纳押金（0.否    1.是  2.退款中  3.退款失败）'
				customersAmountrecord.setAmountId(amountId);
				customersAmountrecord.setAssureTransactionId(transactionId); // 支付订单号
				customersAmountMapper.updateByPrimaryKeySelective(customersAmountrecord);
			}
		}
	}

	/**
	 * @author 刘成
	 * @since 2018年9月28日
	 * @param manageCaseBox
	 * @param openId
	 * 
	 *            微信小程序开箱逻辑（医用床）
	 * @throws Exception
	 */
	@Override
	public void openBoxByXcx(ManageCaseBox manageCaseBox, String openId) throws Exception {
		Date date = new Date();
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCreateTime(date);
		accessRecord.setSource((byte) 3);
		accessRecord.setType((byte) 7);
		accessRecord.setUserId(openId);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		//
		ManageCaseBox manageCaseBox1 = new ManageCaseBox();
		manageCaseBox1.setSwitchStatus((byte) 1);
		manageCaseBox1.setSaveTime(date);
		manageCaseBox1.setUseStatus((byte) 1);
		manageCaseBox1.setUserId(openId);
		manageCaseBox1.setSaveSource((byte) 2);
		manageCaseBox1.setVersion(manageCaseBox.getVersion() + 1);
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andVersionEqualTo(manageCaseBox.getVersion()).andIdEqualTo(manageCaseBox.getId());

		accessRecordMapper.insertSelective(accessRecord);
		manageCaseBoxMapper.updateByExampleSelective(manageCaseBox1, example);

	}

	/**
	 * @author 刘成
	 * @since 2018年9月13日
	 * @param manageCaseBox
	 * @param openId
	 *            支付宝小程序开箱逻辑（医用床）
	 */
	@Override
	public void openBoxByAliXcx(ManageCaseBox manageCaseBox, String openId) throws Exception {
		Date date = new Date();
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCreateTime(date);
		accessRecord.setSource((byte) 5);
		accessRecord.setType((byte) 7);
		accessRecord.setUserId(openId);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		//
		ManageCaseBox manageCaseBox1 = new ManageCaseBox();
		manageCaseBox1.setSaveTime(date);
		manageCaseBox1.setSwitchStatus((byte) 1);
		manageCaseBox1.setUserId(openId);
		manageCaseBox1.setUseStatus((byte) 1);
		manageCaseBox1.setVersion(manageCaseBox.getVersion() + 1);
		manageCaseBox1.setSaveSource((byte) 4);
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andVersionEqualTo(manageCaseBox.getVersion()).andIdEqualTo(manageCaseBox.getId());
		accessRecordMapper.insertSelective(accessRecord);
		manageCaseBoxMapper.updateByExampleSelective(manageCaseBox1, example);

	}

	/**
	 * @author 刘成
	 * @since 2018年8月27日
	 * @param map1
	 *            退款请求申请成功的业务处理
	 * @throws Exception
	 */
	@Override
	public void backPayApply(Map<String, String> map1) throws Exception {
		// 1.申请提交成功后，先改变押金状态为退款中
		String amountId = map1.get("amountId");
		CustomersAmount record = new CustomersAmount();
		record.setIsPay((byte) 2);
		record.setAmountId(Integer.valueOf(amountId));
		customersAmountMapper.updateByPrimaryKeySelective(record);
		// 2.在退款的表中插入一条数据
		String transaction_id = map1.get("transaction_id");
		String out_refund_no = map1.get("out_refund_no");
		String refund_id = map1.get("refund_id");
		String refund_fee = map1.get("refund_fee");
		String total_fee = map1.get("total_fee");
		CustomersRefund customersRefund = new CustomersRefund();
		customersRefund.setCreateTime(new Date());
		customersRefund.setOutRefundNo(out_refund_no);
		customersRefund.setRefundFee(Integer.valueOf(refund_fee));
		customersRefund.setRefundId(refund_id);
		customersRefund.setTransactionId(transaction_id);
		customersRefund.setTotalFee(Integer.valueOf(total_fee));
		customersRefundMapper.insertSelective(customersRefund);

	}

	/**
	 * @author 刘成
	 * @since 2018年8月27日
	 * @param doXMLParse
	 *            退款成功的业务逻辑处理
	 */
	@Override
	public void successBackPay(Map<String, String> doXMLParse) {
		String refund_status = doXMLParse.get("refund_status");
		String transaction_id = doXMLParse.get("transaction_id");

		// 1.修改退款表的信息
		CustomersRefund customersRefund = new CustomersRefund();
		customersRefund.setRefundStatus(refund_status);
		customersRefund.setSuccessTime(doXMLParse.get("success_time"));
		customersRefund.setRefundRecvAccout(doXMLParse.get("refund_recv_accout"));

		CustomersRefundExample example = new CustomersRefundExample();
		example.createCriteria().andTransactionIdEqualTo(transaction_id)
				.andOutRefundNoEqualTo(doXMLParse.get("out_refund_no"));
		customersRefundMapper.updateByExampleSelective(customersRefund, example);
		// 2.修改用户账户的押金状态为未缴纳
		CustomersAmount record = new CustomersAmount();
		CustomersAmountExample customersExample = new CustomersAmountExample();
		record.setIsPay((byte) 0);
		customersExample.createCriteria().andAssureTransactionIdEqualTo(transaction_id).andIsPayEqualTo((byte) 2);
		customersAmountMapper.updateByExampleSelective(record, customersExample);

	}

	/**
	 * @author 刘成
	 * @since 2018年8月28日
	 * @param doXMLParse
	 *            退款失败的逻辑处理
	 */
	@Override
	public void failBackPay(Map<String, String> doXMLParse) {

		// 1.修改资金账户的信息为退款失败
		CustomersAmount record = new CustomersAmount();
		CustomersAmountExample customersExample = new CustomersAmountExample();
		record.setIsPay((byte) 3);
		customersExample.createCriteria().andAssureTransactionIdEqualTo(doXMLParse.get("transaction_id"))
				.andIsPayEqualTo((byte) 2);
		customersAmountMapper.updateByExampleSelective(record, customersExample);
		// 2.修改退款信息
		CustomersRefund customersRefund = new CustomersRefund();
		customersRefund.setRefundStatus(doXMLParse.get("refund_status"));

		CustomersRefundExample example = new CustomersRefundExample();
		example.createCriteria().andTransactionIdEqualTo(doXMLParse.get("transaction_id"))
				.andOutRefundNoEqualTo(doXMLParse.get("out_refund_no"));
		customersRefundMapper.updateByExampleSelective(customersRefund, example);

	}

	/**
	 * @author 刘成
	 * @since 2018年9月5日
	 * @param readValue
	 *            医用床费用结算的处理逻辑
	 */
	@Override
	public void closeBoxAndPay(CaseInitVO readValue) {
		double amount = 0;
		long time = 0;
		List<CaseByDoorVO> doorStatus = readValue.getDoor_status();
		Map<Integer, CaseByDoorVO> doorMap = doorStatus.stream()
				.collect(Collectors.toMap(CaseByDoorVO::getDoor, v -> v));
		String caseNo = readValue.getCabinet_ID();

		ManageCaseExample example = new ManageCaseExample();
		example.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> selectByExample2 = manageCaseMapper.selectByExample(example);
		ManageCase caseByCaseNo = selectByExample2.get(0);
		Integer compId = caseByCaseNo.getCompId();

		Byte useType = caseByCaseNo.getUseType();
		if (Byte.valueOf("2").equals(useType)) {// 医用床才会处理，，，其他的不处理

			// 查询储物柜对应的箱子
			ManageCaseBoxExample caseBoxexample = new ManageCaseBoxExample();
			caseBoxexample.createCriteria().andCaseNoEqualTo(caseNo).andIsDelEqualTo((byte) 0);
			List<ManageCaseBox> boxListByCaseNo = manageCaseBoxMapper.selectByExample(caseBoxexample);

			for (ManageCaseBox manageCaseBox : boxListByCaseNo) {
				Integer doorNum = manageCaseBox.getDoorNum();// 几号门
				Byte useStatus = manageCaseBox.getUseStatus();
				if (Byte.valueOf("1").equals(useStatus)) {// 占用中（只有占用中的才会处理）
					CaseByDoorVO caseByDoorVO = doorMap.get(doorNum);
					boolean locked = caseByDoorVO.isLocked();
					if (locked) {// 只有消息队列里的状态为锁门状态才会处理
						// 拿到收费类型Id
						Integer typeId = caseByCaseNo.getTypeId();
						String userId = manageCaseBox.getUserId();
						Byte saveSource = manageCaseBox.getSaveSource();
						// 查询收费标准
						ManageCaseType selectByPrimaryKey = manageCaseTypeMapper.selectByPrimaryKey(typeId);
						// 计算所需费用
						Byte payType = selectByPrimaryKey.getPayType();
						if (Byte.valueOf("1").equals(payType)) {// 0，免费 1.计时//
																// 2.记次
							String price = selectByPrimaryKey.getPrice();
							String userTime = selectByPrimaryKey.getUserTime();
							double useprice = Double.valueOf(price);
							double usetime = Double.valueOf(userTime);
							// 使用时间
							String timestamp = readValue.getTimestamp();
							long endTime = Long.valueOf(timestamp);
							Date saveTime = manageCaseBox.getSaveTime();
							long startTime = saveTime.getTime();
							time = endTime - startTime;
							double paytime = new BigDecimal(time)
									.divide(new BigDecimal(1000 * 60 * 60), 3, BigDecimal.ROUND_HALF_UP).doubleValue();
							int number = (int) ((paytime % usetime) > 0 ? (paytime / usetime) + 1 : paytime / usetime);
							amount = useprice * number;
						} else if (Byte.valueOf("2").equals(payType)) {// 计次
							String timestamp = readValue.getTimestamp();
							long endTime = Long.valueOf(timestamp);
							Date saveTime = manageCaseBox.getSaveTime();
							long startTime = saveTime.getTime();
							time = endTime - startTime;
							String price = selectByPrimaryKey.getPrice();
							amount = Double.valueOf(price);
						}

						if (Byte.valueOf("2").equals(saveSource) || Byte.valueOf("4").equals(saveSource)) {// 微信小程序或者支付宝小程序
							if (compId != null) {
								// 查询所属公司
								ManageComp comp = manageCompMapper.selectByPrimaryKey(compId);
								if (comp != null) {
									// String aliOpenid = comp.getAliOpenid();
									// String weixinOpenid =
									// comp.getWeixinOpenid();
									// if (aliOpenid == null && weixinOpenid ==
									// null) {// 未绑定微信和支付宝的收款账户，直接打到公司的账户余额中去
									ManageComp manageComp = new ManageComp();
									BigDecimal compBalance = comp.getCompBalance();
									double doubleValue = compBalance.doubleValue();
									double newBalance = doubleValue + amount;
									manageComp.setCompBalance(BigDecimal.valueOf(newBalance));
									manageComp.setCompId(compId);
									manageCompMapper.updateByPrimaryKeySelective(manageComp);
									// } else {
									// 绑定了，，直接调用转账接口
									// TODO
									// }
								}

							}
							CustomersAmountExample amountexample = new CustomersAmountExample();
							amountexample.createCriteria().andOpenIdEqualTo(userId);
							List<CustomersAmount> selectByExample = customersAmountMapper
									.selectByExample(amountexample);
							if (!selectByExample.isEmpty()) {
								// 修改用户资金账户
								CustomersAmount customersAmount = selectByExample.get(0);
								Integer amountId = customersAmount.getAmountId();
								BigDecimal totalAmount = customersAmount.getTotalAmount();
								double doubleValue = totalAmount.doubleValue();
								double newTotalAmount = doubleValue - amount;
								CustomersAmount record = new CustomersAmount();
								record.setAmountId(amountId);
								record.setTotalAmount(BigDecimal.valueOf(newTotalAmount));
								customersAmountMapper.updateByPrimaryKeySelective(record);
								// 修改状态为空闲
								ManageCaseBox manageCaseBox1 = new ManageCaseBox();
								manageCaseBox1.setUseStatus((byte) 0);
								manageCaseBox1.setId(manageCaseBox.getId());
								manageCaseBox1.setVersion(manageCaseBox.getVersion());
								manageCaseBoxMapper.updateByPrimaryKeySelective(manageCaseBox1);
								// 插入一条归还记录

								Date date = new Date();
								AccessRecord t = new AccessRecord();
								if (Byte.valueOf("2").equals(saveSource)) {// 微信小程序
									t.setSource((byte) 3);
								} else if (Byte.valueOf("4").equals(saveSource)) {// 支付宝小程序
									t.setSource((byte) 5);
								}
								t.setBoxId(manageCaseBox.getId());
								t.setCreateTime(date);
								t.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
								t.setType((byte) 6);
								t.setUserId(userId);
								t.setCharge(BigDecimal.valueOf(amount));
								t.setUseTime(time);
								accessRecordMapper.insertSelective(t);
							}
						}
					}
				}

			}
		}
	}

	@Override
	public void payFinishByAli(PayOrder payOrder) {
		Integer orderId = payOrder.getOrderId();
		Integer totalFee = payOrder.getTotalFee();
		String openId = payOrder.getOpenId();
		PayOrder updatePayOrder = new PayOrder();
		updatePayOrder.setOrderId(orderId);
		updatePayOrder.setIsPay((byte) 1);
		payOrderMapper.updateByPrimaryKeySelective(updatePayOrder);
		// 3.修改用户资金账户余额
		CustomersAmountExample example1 = new CustomersAmountExample();
		example1.createCriteria().andOpenIdEqualTo(openId);
		List<CustomersAmount> selectByExample2 = customersAmountMapper.selectByExample(example1);
		if (!selectByExample2.isEmpty()) {
			double amout = new BigDecimal(totalFee).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP)
					.doubleValue();
			CustomersAmount customersAmount = selectByExample2.get(0);
			BigDecimal totalAmount = customersAmount.getTotalAmount();
			double doubleValue = totalAmount.doubleValue();
			double newAmount = doubleValue + amout;
			CustomersAmount record = new CustomersAmount();
			record.setTotalAmount(BigDecimal.valueOf(newAmount));
			record.setAmountId(customersAmount.getAmountId());
			customersAmountMapper.updateByPrimaryKeySelective(record);
		}
	}

	/**
	 * @author 刘成
	 * @since 2018年9月20日
	 * @param payOrder
	 *            支付宝押金缴付成功后的逻辑处理
	 */
	@Override
	public void payCaseFinish(PayOrder payOrder) {
		String openId = payOrder.getOpenId();
		String transactionId = payOrder.getTransactionId();
		Integer totalFee = payOrder.getTotalFee();// 单位为分
		Integer orderId = payOrder.getOrderId();
		PayOrder record = new PayOrder();
		record.setOrderId(orderId);
		record.setIsPay((byte) 1);
		payOrderMapper.updateByPrimaryKeySelective(record);
		// 2.修改资金账户的押金数量、修改状态为已缴纳押金

		BigDecimal divide = new BigDecimal(totalFee).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
		CustomersAmountExample amountExample = new CustomersAmountExample();
		CustomersAmount amountRecord = new CustomersAmount();
		amountExample.createCriteria().andOpenIdEqualTo(openId);
		amountRecord.setIsPay((byte) 1);
		amountRecord.setAssureAmount(divide);
		amountRecord.setAssureTransactionId(transactionId);
		customersAmountMapper.updateByExampleSelective(amountRecord, amountExample);

	}



	/**
	 * @author 刘成
	 * @since 2018年10月15日
	 * @param manageCaseBox
	 * @param openId
	 * @param clearHour 储物超时时间
	 * @param payType 收费类型
	 * @param payTime 收费时间（1.使用后收费  2.使用前收费）
	 *            支付宝、微信 小程序，开启普通柜(存物)
	 * @throws Exception
	 * @throws Exception
	 */
	@Override
	public void openBoxCommonByXcx(ManageCaseBox manageCaseBox, String openId, Byte type, Byte source, Byte saveSource,
								   Integer clearHour, Byte payType, Byte payTime, String password) throws Exception {
		Date date = new Date();

		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.HOUR_OF_DAY, clearHour);

		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCreateTime(date);
		accessRecord.setType(type);
		accessRecord.setSource(source);
		accessRecord.setUserId(openId);

		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));

		accessRecordMapper.insertSelective(accessRecord); // 开箱记录
		ManageCaseBox manageCaseBox1 = new ManageCaseBox();
		manageCaseBox1.setSaveTime(date);
		manageCaseBox1.setUserId(openId);
		manageCaseBox1.setUseStatus((byte) 1);
		manageCaseBox1.setVersion(manageCaseBox.getVersion() + 1);
		manageCaseBox1.setSaveSource(saveSource);
		manageCaseBox1.setClearBoxTime(calendar.getTime());
		if (password != null && !"".equals(password)) {
			manageCaseBox1.setPassword(Md5Util.sha1(password));
		}
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andVersionEqualTo(manageCaseBox.getVersion()).andIdEqualTo(manageCaseBox.getId())
				.andUseStatusEqualTo((byte) 0);

		int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(manageCaseBox1, example); // 修改箱子状态
		if (updateByExampleSelective == 0) {
			throw new Exception();
		}
		// 开门
		Integer doorNum = manageCaseBox.getDoorNum();
		String caseNo = manageCaseBox.getCaseNo();
		Connection connection = ConnectionUtils.getConnection();
		Channel channel = connection.createChannel();
		Map<String, Object> sendMap = new HashMap<>();
		sendMap.put("door", doorNum);
		sendMap.put("timestamp", date.getTime());
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-message-ttl", 40000);
		channel.queueDeclare(caseNo, true, false, false, args);
		String writeValueAsString = mapper.writeValueAsString(sendMap);
		channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
		channel.close();
		connection.close();
	}

	/**
	 *
	 *
	 * @author 谭芸
	 * @since 2021年4月2
	 * @param manageCaseBox
	 * @param openId
	 * @param clearHour 储物超时时间
	 * @param payType 收费类型
	 * @param payTime 收费时间（1.使用后收费  2.使用前收费）
	 *            支付宝、微信 小程序，开启普通柜(存物)
	 * @throws Exception
	 * @throws Exception
	 */
	@Override
	public void openBoxCommonByNewXcx(ManageCaseBox manageCaseBox, String openId, Byte type, Byte source, Byte saveSource,
			Integer clearHour, Byte payType, Byte payTime, String aounmt, String priceId) throws Exception {
		Date date = new Date();

		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MINUTE, clearHour);

		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCreateTime(date);
		accessRecord.setType(type);
		accessRecord.setSource(source);
		accessRecord.setUserId(openId);
		accessRecord.setCharge(new BigDecimal(aounmt));
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));

		accessRecordMapper.insertSelective(accessRecord); // 开箱记录
		ManageCaseBox manageCaseBox1 = new ManageCaseBox();
		manageCaseBox1.setSaveTime(date); // 存放时间
		manageCaseBox1.setUserId(openId);
		manageCaseBox1.setUseStatus((byte) 1);
		manageCaseBox1.setVersion(manageCaseBox.getVersion() + 1);
		manageCaseBox1.setSaveSource(saveSource);
		manageCaseBox1.setClearBoxTime(calendar.getTime());
		manageCaseBox1.setCaseTypePriceId(priceId); //存储收费id

		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andVersionEqualTo(manageCaseBox.getVersion()).andIdEqualTo(manageCaseBox.getId())
				.andUseStatusEqualTo((byte) 0);

		int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(manageCaseBox1, example); // 修改箱子状态
		if (updateByExampleSelective == 0) {
			throw new Exception();
		}
		// 开门
		Integer doorNum = manageCaseBox.getDoorNum();
		String caseNo = manageCaseBox.getCaseNo();
		Connection connection = ConnectionUtils.getConnection();
		Channel channel = connection.createChannel();
		Map<String, Object> sendMap = new HashMap<>();
		sendMap.put("door", doorNum);
		sendMap.put("timestamp", date.getTime());
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-message-ttl", 40000);
		channel.queueDeclare(caseNo, true, false, false, args);
		String writeValueAsString = mapper.writeValueAsString(sendMap);
		channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
		channel.close();
		connection.close();
	}


	/**
	 *
	 * @author 谭芸
	 * @since 2021年4月5
	 * @param manageCaseBox
	 * @param openId
	 * @param clearHour 储物超时时间
	 *            支付宝、微信 小程序，开启普通柜(还车)
	 * @throws Exception
	 * @throws Exception
	 */
	public void openBoxCommonByNewXcx(ManageCaseBox manageCaseBox, String openId, Byte type, Byte source, Byte saveSource,
									  Integer clearHour, String aounmt) throws Exception {
		Date date = new Date();

		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MINUTE, clearHour);

		ManageCaseBox manageCaseBox1 = new ManageCaseBox();
		manageCaseBox1.setSaveTime(date); // 存放时间
		manageCaseBox1.setUserId(openId);
		manageCaseBox1.setUseStatus((byte) 0);
		manageCaseBox1.setVersion(manageCaseBox.getVersion() + 1);
		manageCaseBox1.setSaveSource(saveSource);
		manageCaseBox1.setClearBoxTime(calendar.getTime());

		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andVersionEqualTo(manageCaseBox.getVersion()).andIdEqualTo(manageCaseBox.getId())
				.andUseStatusEqualTo((byte) 1);

		int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(manageCaseBox1, example); // 修改箱子状态
		if (updateByExampleSelective == 0) {
			throw new Exception();
		}

		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCreateTime(date);
		accessRecord.setType(type);  // 类型
		accessRecord.setSource(source);
		accessRecord.setUserId(openId);
		accessRecord.setCharge(new BigDecimal(aounmt));
		Date saveTime = manageCaseBox.getSaveTime();
		accessRecord.setUseTime(new Date().getTime() - saveTime.getTime()); // 使用时长
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecordMapper.insertSelective(accessRecord); // 开箱记录

		// 开门
		Integer doorNum = manageCaseBox.getDoorNum();
		String caseNo = manageCaseBox.getCaseNo();
		Connection connection = ConnectionUtils.getConnection();
		Channel channel = connection.createChannel();
		Map<String, Object> sendMap = new HashMap<>();
		sendMap.put("door", doorNum);
		sendMap.put("timestamp", date.getTime());
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-message-ttl", 40000);
		channel.queueDeclare(caseNo, true, false, false, args);
		String writeValueAsString = mapper.writeValueAsString(sendMap);
		channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
		channel.close();
		connection.close();
	}



	/**
	 * @author 刘成
	 * @since 2018年10月17日
	 * @param payOrder
	 * @param manageCaseBox
	 * @param manageCase
	 * @param time
	 *            常规储物柜支付成功后的取物逻辑
	 */
	@Override
	public void payFinishByAliAndCommonBox(PayOrder payOrder, ManageCaseBox manageCaseBox, ManageCase manageCase,
			Long time) {
		Date date = new Date();
		Integer compId = manageCase.getCompId();
		ManageComp selectByPrimaryKey = manageCompMapper.selectByPrimaryKey(compId);
		Integer id = manageCaseBox.getId();
		Integer totalFee = payOrder.getTotalFee();
		BigDecimal compBalance = selectByPrimaryKey.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double money = new BigDecimal(totalFee).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP).doubleValue();
		double newTotalAmount = doubleValue + money;

		// 2.修改订单状态
		PayOrder record = new PayOrder();
		record.setIsPay((byte) 1);
		record.setOrderId(payOrder.getOrderId());
		payOrderMapper.updateByPrimaryKeySelective(record);
		// 3.插入记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(id);
		accessRecord.setCharge(BigDecimal.valueOf(money));
		accessRecord.setCreateTime(date);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecord.setSource((byte) 5);
		accessRecord.setType((byte) 2);
		accessRecord.setUserId(manageCaseBox.getUserId());
		accessRecord.setUseTime(time);
		accessRecordMapper.insertSelective(accessRecord);

		// 4.修改储物柜状态
		ManageCaseBox caseBoxRecord = new ManageCaseBox();
		caseBoxRecord.setId(id);
		caseBoxRecord.setPassword("0-0!!!");// 清空密码
		caseBoxRecord.setUseStatus((byte) 0);
		manageCaseBoxMapper.updateByPrimaryKeySelective(caseBoxRecord);

		// 5.转账或修改公司账户信息
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);
	}

	/**
	 * @author 刘成
	 * @since 2018年10月17日
	 * @param payOrder
	 * @param manageCaseBox
	 * @param manageCase
	 * @param time
	 *            常规储物柜支付成功后的清除逻辑
	 */
	@Override
	public void clearPayFinishByAli(PayOrder payOrder, ManageCaseBox manageCaseBox, ManageCase manageCase, Long time) {
		Date date = new Date();
		Integer compId = manageCase.getCompId();
		ManageComp selectByPrimaryKey = manageCompMapper.selectByPrimaryKey(compId);
		Integer id = manageCaseBox.getId();
		Integer totalFee = payOrder.getTotalFee();
		BigDecimal compBalance = selectByPrimaryKey.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double money = new BigDecimal(totalFee).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP).doubleValue();
		double newTotalAmount = doubleValue + money;

		// 2.修改订单状态
		PayOrder record = new PayOrder();
		record.setIsPay((byte) 1);
		record.setOrderId(payOrder.getOrderId());
		payOrderMapper.updateByPrimaryKeySelective(record);
		// 3.插入记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(id);
		accessRecord.setCharge(BigDecimal.valueOf(money));
		accessRecord.setCreateTime(date);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecord.setSource((byte) 5);
		accessRecord.setType((byte) 2);
		accessRecord.setUserId(manageCaseBox.getUserId());
		accessRecord.setUseTime(time);
		accessRecordMapper.insertSelective(accessRecord);

		// 5.转账或修改公司账户信息
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);
	}

	/**
	 * @author 刘成
	 * @since 2018年10月17日
	 * @param payOrder
	 * @param manageCaseBox
	 * @param manageCase
	 * @param time
	 *            常规储物柜支付成功后的清除逻辑
	 */
	@Override
	public void clearPayFinishByWx(PayOrder payOrder, ManageCaseBox manageCaseBox, ManageCase manageCase, Long time) {
		Date date = new Date();
		Integer compId = manageCase.getCompId();
		ManageComp selectByPrimaryKey = manageCompMapper.selectByPrimaryKey(compId);
		Integer id = manageCaseBox.getId();
		Integer totalFee = payOrder.getTotalFee();
		BigDecimal compBalance = selectByPrimaryKey.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double money = new BigDecimal(totalFee).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP).doubleValue();
		double newTotalAmount = doubleValue + money;

		// 2.修改订单状态
		PayOrder record = new PayOrder();
		record.setIsPay((byte) 1);
		record.setOrderId(payOrder.getOrderId());
		payOrderMapper.updateByPrimaryKeySelective(record);
		// 3.插入记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(id);
		accessRecord.setCharge(BigDecimal.valueOf(money));
		accessRecord.setCreateTime(date);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecord.setSource((byte) 3);
		accessRecord.setType((byte) 2);
		accessRecord.setUserId(manageCaseBox.getUserId());
		accessRecord.setUseTime(time);
		accessRecordMapper.insertSelective(accessRecord);

		// 5.转账或修改公司账户信息
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);
	}

	@Override
	public Map<String, Object> carRental(ManageCaseBoxVO vo) {
		Map<String, Object> map = new HashMap<>();
		String caseNo = vo.getCaseNo();
		String openId = vo.getUserId();
		Integer priceId = vo.getPriceId();
		ManageCaseTypePriceExample example = new ManageCaseTypePriceExample();
		ManageCaseTypePriceExample.Criteria criteria = example.createCriteria().andIdEqualTo(priceId);
		List<ManageCaseTypePrice> manageCaseTypePrices = manageCaseTypePriceMapper.selectByExample(example);
		if (manageCaseTypePrices == null || manageCaseTypePrices.size() == 0){
			ReturnMapUtils.genarateMap(map, "收费类型错误！！");
		}
		ManageCaseTypePrice manageCaseTypePrice = manageCaseTypePrices.get(0); // 收费信息
		List<ManageCase> manageCases = manageCaseMapper.selectInCaseNo(Arrays.asList(caseNo));
		ManageCase manageCase = manageCases.get(0);

		// 可以开启的柜子列表
		List<ManageCaseBox> integers = this.availableCabinet(caseNo);
		if (integers == null && integers.size() == 0){
			ReturnMapUtils.genarateMap(map, "当前没有可用箱子！！");
		}

		Random rand = new Random();
		ManageCaseBox manageCaseBox = integers.get(rand.nextInt(integers.size())); // 随机抽取一个可用的箱子
		Integer doorNum = manageCaseBox.getDoorNum(); // 抽取的箱子门牌号
		Integer boxId = manageCaseBox.getId();  // 箱子id
		String amountF = manageCaseTypePrice.getThePrice();
		Integer amountY = 0; // 转为元 需要提交支付的金额
		try {
			amountY = Integer.valueOf(AmountUtils.changeF2Y(amountF));
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 查询用户账户余额是否足够支付提交支付的金额， 够则从余额中扣款，否则调用支付接口
		CustomersAmount customersAmount = customersAmountMapper.selectByOpenid(openId);
		BigDecimal totalAmount = customersAmount.getTotalAmount();
		if (totalAmount.compareTo(new BigDecimal(amountY)) == -1) {
			// 用户资金不足以支付 提前支付的金额 调用支付接口

			Date date = new Date();
			String notify_url = WxConfig.DOMAIN_URL + "/wxCommonxcx/cartFeeCallback";
//			String place = manageCase.getPlace();
			String caseNoBuy = manageCase.getCaseNoBuy().length() == 0 ? "" : manageCase.getCaseNoBuy() + "--";
			String body =  manageCase.getPlace() + "--" + caseNoBuy + doorNum + "号门" + "--租车";
			// 产生随机数
			String nonce_str = DictionaryUtils.getRandomStr();
			String out_trade_no = "XF_wx" + date.getTime() + nonce_str.substring(0, 2);

			try {
				map = prepayWeiXin(notify_url, body, nonce_str, out_trade_no, amountY, openId, boxId, priceId,"");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			map.put("pagejump", "8");
			map.put("doorNum", doorNum);

			return map;

		} else {
			// 先在支付记录表记录即将要支付的金额， 返回一个消息，小程序点击确定即可进行扣费开门
			PayOrder payOrder = new PayOrder();
			payOrder.setOpenId(openId);
			payOrder.setCreartTime(new Date());
			payOrder.setBoxId(boxId);
			payOrder.setIsPay((byte) 0); // 状态为未支付
			payOrder.setTotalFee(Integer.valueOf(amountF)); // 金额
			payOrder.setTransactionId("用户余额扣款");
			payOrder.setOutTradeNo("用户余额扣款");
			int sNumber = payOrderMapper.insertSelective(payOrder);
			if (sNumber != 1){
				ReturnMapUtils.genarateMap(map, "请稍后重试！！");
				return map;
			}
			map.put("pagejump", "4");
			map.put("boxId", boxId);
			map.put("hzmessageyy", "将从余额中进行扣费开箱，点击确定扣费");
			return map;
		}
	}

	@Override
	public Map<String, Object> chargesForUnpacking(PayOrder payOrder, String priceId) {
		Map<String, Object> map = new HashMap<>();
		String openId = payOrder.getOpenId();
		Integer boxId = payOrder.getBoxId();
		//1.查询是否存在此订单
		PayOrderExample example = new PayOrderExample();
		example.createCriteria().andOpenIdEqualTo(openId).andBoxIdEqualTo(boxId).andIsPayEqualTo((byte) 0);
		List<PayOrder> payOrders = payOrderMapper.selectByExample(example);
		if (payOrders == null || payOrders.size() == 0){
			ReturnMapUtils.genarateMap(map, "操作失败！");
			return map;
		}
		//2.查询此箱子是否被占用
		ManageCaseBoxExample manageCaseBoxExample = new ManageCaseBoxExample();
		manageCaseBoxExample.createCriteria().andIdEqualTo(boxId).andUseStatusEqualTo((byte) 0).andIsConnEqualTo((byte) 1);
		List<ManageCaseBox> manageCaseBoxes = manageCaseBoxMapper.selectByExample(manageCaseBoxExample);
		ManageCaseBox manageCaseBox = manageCaseBoxes.get(0);
		//2.1没被占用就开此箱子，被占用则查询有没有其它箱子可用
		if (manageCaseBoxes == null || manageCaseBoxes.size() == 0){
			//箱子被占用
			// 箱子已被占用, 重新选一个没有被使用的箱子
			List<ManageCaseBox> manageCaseBoxeList = availableCabinet(manageCaseBox.getCaseNo());
			if (manageCaseBoxeList == null || manageCaseBoxeList.size() == 0) throw new RuntimeException("没有可用的箱子");
			Random rand = new Random();
			manageCaseBox = manageCaseBoxeList.get(rand.nextInt(manageCaseBoxeList.size())); // 随机抽取一个可用的箱子

		}

		payOrder = payOrders.get(0);
		Integer totalFee = payOrder.getTotalFee(); // 扣费金额
		String amountY = "";

		Integer theLenght = manageCaseTypePriceMapper.selectByPrimaryKey(priceId).getTheLenght(); // 多久后超时
		//3.开箱
		try {
			amountY = AmountUtils.changeF2Y(totalFee + ""); // 分转为元 即将扣费的金额
			openBoxCommonByNewXcx(manageCaseBox, openId, AllConst.ACCESS_RECORD_TYPE.BORROW_TYEP,
					AllConst.ACCESS_RECORD_SOURCE.WX_XCX_SOURCE, AllConst.CASE_BOX_SAVE_SOURCE.WX_XCX_SAVE_SOURCE,
					theLenght, (byte) 1, (byte) 2,amountY, priceId);
		} catch (Exception e) {
			log.error(e);
			ReturnMapUtils.genarateMap(map, "扣费开箱失败！");
			return map;
		}

		//4.扣款，设置订单状态
		try {
			BigDecimal deduction = new BigDecimal(amountY);
			// 扣款
			CustomersAmount customersAmount = customersAmountMapper.selectByOpenid(openId);
			BigDecimal totalAmount = customersAmount.getTotalAmount();
			BigDecimal remaining = totalAmount.subtract(deduction);
			customersAmount.setTotalAmount(remaining);
			int i = customersAmountMapper.updateByPrimaryKey(customersAmount);
			if (i == 0){
				throw new RuntimeException("扣费失败");
			}

		} catch (Exception e) {
			e.printStackTrace();
			ReturnMapUtils.genarateMap(map, "扣费失败！请稍后重试");
			return map;
		}

		payOrder.setIsPay((byte) 1); //设置为已支付
		int returnEd = payOrderMapper.updateByPrimaryKey(payOrder);

		map.put("hzmessageyy", "开箱成功");
		return map;
	}


	/**
	 * 从账户中扣费  续时
	 * @param caseBox
	 * @return
	 */
	@Override
	public Map<String, Object> continuedUse(ManageCaseBox caseBox) {
		Map<String, Object> map = new HashMap<>();
		String openId = caseBox.getUserId();
		Integer boxId = caseBox.getId();
		//1. 修改用户账户余额
		CustomersAmount customersAmount = customersAmountMapper.selectByOpenid(openId); // 账户信息

		PayOrderExample example = new PayOrderExample();
		example.createCriteria().andOpenIdEqualTo(openId).andBoxIdEqualTo(boxId).andIsPayEqualTo((byte) 0);
		List<PayOrder> payOrders = payOrderMapper.selectByExample(example);
		if (payOrders == null || payOrders.size() == 0){
			ReturnMapUtils.genarateMap(map, "没有查询到订单！");
		}
		PayOrder payOrder = payOrders.get(0);
		Integer totalFee = payOrder.getTotalFee(); // 订单金额，单位分
		String yuan = "0";
		try {
			yuan = AmountUtils.changeF2Y(totalFee + "");
		} catch (Exception e) {
			e.printStackTrace();
		}
		BigDecimal totalAmount = customersAmount.getTotalAmount(); // 用户余额 单位元
		totalAmount = totalAmount.subtract(new BigDecimal(yuan));
		customersAmount.setTotalAmount(totalAmount);
		customersAmountMapper.updateByPrimaryKey(customersAmount);

		// 2.修改订单为已支付
		payOrder.setIsPay((byte) 1);
		payOrderMapper.updateByPrimaryKey(payOrder);

		// 3. 设置箱子超时时间
		ManageCaseBoxExample manageCaseBoxExample = new ManageCaseBoxExample();
		manageCaseBoxExample.createCriteria().andIdEqualTo(boxId).andUseStatusEqualTo((byte) 1).andIsConnEqualTo((byte) 1);
		List<ManageCaseBox> manageCaseBoxes = manageCaseBoxMapper.selectByExample(manageCaseBoxExample);
		ManageCaseBox manageCaseBox = manageCaseBoxes.get(0); // 箱子信息
		String caseTypePriceId = manageCaseBox.getCaseTypePriceId();
		ManageCaseTypePrice manageCaseTypePrice = manageCaseTypePriceMapper.selectByPrimaryKey(caseTypePriceId); // 收费规则信息
		String thePrice = manageCaseTypePrice.getThePrice();
		Integer theLenght = manageCaseTypePrice.getTheLenght();
		int period = totalFee % Double.valueOf(thePrice) > 0 ? totalFee / Integer.valueOf(thePrice) + 1 :
				totalFee / Integer.valueOf(thePrice);  // 得出是给了几个周期的费用
		int delayedTime = period * theLenght; // 延时多久 单位分钟
		Date clearBoxTime = manageCaseBox.getClearBoxTime(); // 现在的到期时间
		Calendar cal = Calendar.getInstance();
		cal.setTime(clearBoxTime);
		cal.add(Calendar.MINUTE, delayedTime);
		manageCaseBox.setClearBoxTime(cal.getTime());
		manageCaseBoxMapper.updateByPrimaryKey(manageCaseBox);  // 修改超时时间


		// 4.添加一条记录
		Date date = new Date();
		String amount = null;
		try {
			amount = AmountUtils.changeF2Y(totalFee+"");
		} catch (Exception e) {
			e.printStackTrace();
		}
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCreateTime(date);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.CONTINUE_USE);  // 类型
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.WX_XCX_SOURCE);
		accessRecord.setUserId(openId);
		accessRecord.setCharge(new BigDecimal(amount));
		Date saveTime = manageCaseBox.getSaveTime();
		accessRecord.setUseTime(new Date().getTime() - saveTime.getTime()); // 使用时长
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecordMapper.insertSelective(accessRecord); // 开箱记录

		map.put("pagejump", "200");
		map.put("hzmessageyy", "续时成功");
		return map;
	}



	/**
	 * 结束使用 还车
	 * @param boxVO
	 * @return
	 */
	@Override
	public Map<String, Object> endUse(ManageCaseBox boxVO) {
		Map<String, Object> map = new HashMap<>();
		Date date = new Date();
		// 1.查询箱子相关信息
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andIdEqualTo(boxVO.getId()).andUserIdEqualTo(boxVO.getUserId()).andUseStatusEqualTo((byte)1);
		List<ManageCaseBox> manageCaseBoxes = manageCaseBoxMapper.selectByExample(example);
		if (manageCaseBoxes == null) {
			ReturnMapUtils.genarateMap(map,"箱子是空闲状态");
			return map;
		}
		// 2.查询收费规则相关信息
		ManageCaseBox manageCaseBox = manageCaseBoxes.get(0);
		String id = manageCaseBox.getCaseTypePriceId();
		ManageCaseTypePrice manageCaseTypePrice = manageCaseTypePriceMapper.selectByPrimaryKey(id);

		String price = manageCaseTypePrice.getThePrice(); // 单位分
		Integer userTime = manageCaseTypePrice.getTheLenght();
		Date saveTime = manageCaseBox.getSaveTime(); // 开始存物时间

		BigDecimal cost = new BigDecimal(0); //花费
		long endTime = date.getTime();
		long startTime = saveTime.getTime(); // 开始存物时间
		long time = endTime - startTime; //取物时间 - 存物时间 得出存了多久
		Date clearBoxTime = manageCaseBox.getClearBoxTime(); //超时时间
		Long amount = getPayBeforeCharge(time, Long.parseLong(price), userTime+"",clearBoxTime); // 计算要支付的金额
		String amountY = "0";
		try {
			amountY = AmountUtils.changeF2Y(amount+""); // 转为元
		} catch (Exception e) {
			e.printStackTrace();
		}
		if (Integer.valueOf(amountY) == 0){
			// 不需要额外缴费，直接开箱
			try {
				String openId = boxVO.getUserId();
				openMyCommonBoxByXcx(manageCaseBox, openId, AllConst.ACCESS_RECORD_TYPE.REPAY_TYEP,
						AllConst.ACCESS_RECORD_SOURCE.WX_XCX_SOURCE,cost);
				map.put("code", "200");
				map.put("openboxMessage", "已为您开启箱" + manageCaseBox.getDoorNum() + "号箱门，请归还玩具车，并关好箱门！");
				return map;
			} catch (Exception e) {
				map.put("code", "500");
				map.put("openboxMessage", "开启失败，请重试");
				return map;
			}

		} else {
			// 超时，需要额外收费
			System.err.println("需要额外交的金额为：  " + amountY);
			String caseNo = manageCaseBox.getCaseNo();
			ManageCaseExample example1  = new ManageCaseExample();
			example.createCriteria().andCaseNoEqualTo(caseNo);
			ManageCase manageCase = manageCaseMapper.selectByExample(example1).get(0);
			return this.overtimePayment(manageCaseBox.getUserId(), amountY,manageCase, map, manageCaseBox );
		}


	}


	/**
	 * 柜子续时使用
	 * @param caseBox
	 * @return
	 */
	@Override
	public Map<String, Object> continued(ManageCaseBox caseBox) {
		Map<String, Object> map = new HashMap<>();
		Integer id = caseBox.getId();
		// 1. 柜子是否超时，超时才能进行续时
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		ManageCaseBox manageCaseBox = manageCaseBoxMapper.selectByPrimaryKey(id);
		Date clearBoxTime = manageCaseBox.getClearBoxTime();
		if (clearBoxTime.getTime() > new Date().getTime()) { // 还没有超时，不需要续时
			String startTimeStr = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(clearBoxTime);
			map.put("openboxMessage","您还没有超时不用进行续时操作哦。超时时间： " + startTimeStr);
			return map;
		}
		// 2.超时，判断是扣除账户余额 还是 调用支付
		String userId = caseBox.getUserId();
		CustomersAmount customersAmount = customersAmountMapper.selectByOpenid(userId); // 用户账户信息
		String caseTypePriceId = manageCaseBox.getCaseTypePriceId(); // 收费id
		ManageCaseTypePrice manageCaseTypePrice = manageCaseTypePriceMapper.selectByPrimaryKey(caseTypePriceId); // 收费信息
		String thePrice = manageCaseTypePrice.getThePrice(); // 续时一周期的费用
		Integer theLenght = manageCaseTypePrice.getTheLenght();
		BigDecimal totalAmount = customersAmount.getTotalAmount(); // 用户账户余额
		String f = AmountUtils.changeY2F(totalAmount.toString()); // 将余额转为分
		Long amount = getPayBeforeCharge(0L, Long.parseLong(thePrice), theLenght + "", clearBoxTime);// 计算要支付的金额

		if (new BigDecimal(amount).compareTo(new BigDecimal(f)) == 1) { // 余额不足，调用支付接口
			// 用户资金不足以支付 提前支付的金额 调用支付接口
			Integer doorNum = manageCaseBox.getDoorNum();
			ManageCaseExample manageCaseExample = new ManageCaseExample();
			manageCaseExample.createCriteria().andCaseNoEqualTo(manageCaseBox.getCaseNo());
			List<ManageCase> manageCases = manageCaseMapper.selectByExample(manageCaseExample);
			ManageCase manageCase = manageCases.get(0); // 柜子信息

			Date date = new Date();
			String notify_url = WxConfig.DOMAIN_URL + "/wxCommonxcx/continuedUseCallback";
//			String place = manageCase.getPlace();
			String caseNoBuy = manageCase.getCaseNoBuy().length() == 0 ? "" : manageCase.getCaseNoBuy() + "--";
			String body =  manageCase.getPlace() + "--" + caseNoBuy + doorNum + "号门" + "--续时使用";
			// 产生随机数
			String nonce_str = DictionaryUtils.getRandomStr();
			String out_trade_no = "XS_wx" + date.getTime() + nonce_str.substring(0, 2);
			String amountY = "0";
			try {
				amountY = AmountUtils.changeF2Y(amount + "");
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				String priceId = manageCaseBox.getCaseTypePriceId();
				map = prepayWeiXin(notify_url, body, nonce_str, out_trade_no, Integer.valueOf(amountY), userId, manageCaseBox.getId(), Integer.valueOf(priceId),"");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			map.put("pagejump", "8");
			map.put("doorNum", doorNum);

			return map;
		} else {
			PayOrder payOrder = new PayOrder();
			payOrder.setOpenId(userId);
			payOrder.setCreartTime(new Date());
			payOrder.setBoxId(id);
			payOrder.setIsPay((byte) 0); // 状态为未支付
			payOrder.setTotalFee(new Long(amount).intValue()); // 金额
			payOrder.setTransactionId("用户余额扣款");
			payOrder.setOutTradeNo("用户余额扣款");
			int sNumber = payOrderMapper.insertSelective(payOrder);
			if (sNumber != 1){
				ReturnMapUtils.genarateMap(map, "请稍后重试！！");
				return map;
			}

			map.put("boxId", id);
			map.put("pagejump", "301");
			map.put("openboxMessage","点击确定将从账户余额中进行扣费");
		}

		return map;
	}


	/**
	 * 超时支付
	 * 		如果余额足以支付超时的金额 直接扣除余额，否则拉起支付窗口
	 * @param openId 用户
	 * @param amountY 金额
	 * @param manageCase 柜子
	 * @param map
	 * @param manageCaseBox 当前处理的箱子信息
	 * @return
	 */
	private Map<String, Object> overtimePayment(String openId, String amountY, ManageCase manageCase, Map<String, Object> map, ManageCaseBox manageCaseBox) {
		CustomersAmount customersAmount = customersAmountMapper.selectByOpenid(openId);
		BigDecimal totalAmount = customersAmount.getTotalAmount();
		Integer doorNum = manageCaseBox.getDoorNum();
		if (totalAmount.compareTo(new BigDecimal(amountY)) == -1) {
			// 用户资金不足以支付 提前支付的金额 调用支付接口
			Date date = new Date();
			String notify_url = WxConfig.DOMAIN_URL + "/wxCommonxcx/overtimeChargeCallback";
//			String place = manageCase.getPlace();
			String caseNoBuy = manageCase.getCaseNoBuy().length() == 0 ? "" : manageCase.getCaseNoBuy() + "--";
			String body =  manageCase.getPlace() + "--" + caseNoBuy + doorNum + "号门" + "--超时费用结算";
			// 产生随机数
			String nonce_str = DictionaryUtils.getRandomStr();
			String out_trade_no = "XF_wx" + date.getTime() + nonce_str.substring(0, 2);

			try {
				String caseTypePriceId = manageCaseBox.getCaseTypePriceId();
				map = prepayWeiXin(notify_url, body, nonce_str, out_trade_no, Integer.valueOf(amountY), openId, manageCaseBox.getId(),Integer.valueOf(caseTypePriceId),"");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			map.put("code", "202");
			map.put("doorNum", doorNum);
			return map;

		} else {
			// 直接扣除余额 开箱
			// 1.开箱
			try {
				openBoxCommonByNewXcx(manageCaseBox, openId, AllConst.ACCESS_RECORD_TYPE.REPAY_TYEP,
						AllConst.ACCESS_RECORD_SOURCE.WX_XCX_SOURCE, AllConst.CASE_BOX_SAVE_SOURCE.WX_XCX_SAVE_SOURCE,
						0,amountY);
			} catch (Exception e) {
				log.error(e);
				map.put("code", "500");
				map.put("openboxMessage", "扣费开箱失败");
				return map;
			}
			 //2.扣款
			try {
				BigDecimal deduction = new BigDecimal(amountY);
				// 扣款
				CustomersAmount userAmount = customersAmountMapper.selectByOpenid(openId);
				BigDecimal balance = userAmount.getTotalAmount();
				BigDecimal remaining = balance.subtract(deduction);
				customersAmount.setTotalAmount(remaining);
				int i = customersAmountMapper.updateByPrimaryKey(customersAmount);
				if (i == 0){
					throw new RuntimeException("扣费失败");
				}

			} catch (Exception e) {
				e.printStackTrace();
				map.put("code", "500");
				map.put("openboxMessage", "扣费失败，请稍后重试");
				return map;
			}
			map.put("code","201");
			map.put("openboxMessage", "开箱成功,已从您的账户余额中扣费，扣费金额： " + amountY + "元");
			return map;
		}
	}


	/**
	 * 收费的金额计算
	 * @param time 使用了多长时间
	 * @param useprice 价格 单位分
	 * @param userTime 时间
	 * @param clearTime 超时时间
	 * @return 返回金额  单位分
	 */
	private static Long getPayBeforeCharge(long time, Long useprice, String userTime, Date clearTime) {
		// 判断当前时间如果小于超时时间，那么就是没有超时，没有超时就直接返回
		long cleartime = clearTime.getTime();
		long nowTime = new Date().getTime();
		BigDecimal clearDecimal = new BigDecimal(cleartime);
		BigDecimal nowDecimal = new BigDecimal(nowTime);
		if (nowDecimal.compareTo(clearDecimal) != 1){
			// 没有超时
			return 0L;
		}
		// 超时
		long overtime = nowTime - cleartime;
		double paytime = new BigDecimal(overtime).divide(new BigDecimal(1000 * 60 ), 3, BigDecimal.ROUND_HALF_UP)
				.doubleValue();
		double usetime = Double.valueOf(userTime);
		// 使用时长向上取整 存储时间 %
		int number = (int) ((paytime % usetime) > 0 ? (paytime / usetime) + 1 : paytime / usetime);
		Long amount = useprice * number ;
		return amount;
	}

	/**
	 * @author 谭芸
	 * @since 2021年4月2日
	 * @param notify_url 微信回调url
	 * @param body
	 * @param nonce_str 随机字符串
	 * @param out_trade_no
	 * @param amount 金额 单位元
	 * @param openId
	 * @param boxId 箱子主键
	 * @param password
	 * @return
	 * @throws UnsupportedEncodingException
	 *             租车的相关订单生成
	 *             会调用微信支付接口 然后将订单号存入表中
	 */
	public Map<String, Object> prepayWeiXin(String notify_url, String body, String nonce_str, String out_trade_no,
											Integer amount, String openId, Integer boxId,Integer priceId,String password)
			throws UnsupportedEncodingException {
        amount = Integer.valueOf(AmountUtils.changeY2F(amount+""));
//        amount = 1;  // 测试设置为1分
		// log.info("发送预付订单！amount:" + amount + " pledge:" + pledge);
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MINUTE, 2);
		Date time = calendar.getTime();
		String time_expire = DateTimeHelper.formatDateTimetoString(time, "yyyyMMddHHmmss");

		Date date = new Date();
		Map<String, Object> map = new HashMap<>();
		String MCHID = WxConfig.MCH_ID;
		String KEY = WxConfig.KEY;
		String appid = WxConfig.APPID;
		Map<String, String> payMap = WxPayBeforUtil.getPayMap(appid, MCHID, nonce_str, body, out_trade_no,
				/*amount*/ 1, openId, notify_url ,time_expire);
		payMap.put("attach","priceId=" + priceId); // 携带额外参数

		String stringA = DictionaryUtils.formatUrlMap(payMap, false, false);
		String stringSignTemp = stringA + "&key=" + KEY;
		String sign = Md5Util.wxXcxHash(stringSignTemp).toUpperCase();

		// 将参数 编写XML格式
		StringBuffer paramBuffer = WxPayBeforUtil.getPayXml(appid, MCHID, nonce_str, body, out_trade_no,
				/*amount*/ 1, openId, notify_url, time_expire,priceId, sign);
		String remotePortData = new WXXcxCommonContrller().getRemotePortData(WxConfig.URL,
				new String(paramBuffer.toString().getBytes("utf-8"), "ISO8859-1"));

		InputStream is = new ByteArrayInputStream(remotePortData.getBytes());
		InputStreamReader isReader = new InputStreamReader(is, "utf-8");
		Map<String, String> map1 = XmlPullUtil.parse(isReader);

		// 拿到接口返回值，插入记录
		String prepay_id = map1.get("prepay_id");
		// 请求订单号成功
		if (StringUtils.isNotBlank(prepay_id)) {
			log.info("订单请求成功！");
			try {
				log.info("插入数据库！");
				payOrderService.prepayWXBefore(date, openId, out_trade_no, amount, new BigDecimal(0), boxId, prepay_id, password);
				long seconds = date.getTime();
				Map<String, String> paySignMap = new HashMap<>();
				paySignMap.put("appId", appid);
				paySignMap.put("timeStamp", String.valueOf(seconds));
				paySignMap.put("nonceStr", nonce_str);
				paySignMap.put("package", "prepay_id=" + prepay_id);
				paySignMap.put("signType", "MD5");
				String stringPay = DictionaryUtils.formatUrlMap(paySignMap, false, false);
				String paySign = WXMD5Util.MD5Encode(stringPay + "&key=" + KEY).toUpperCase();
				map.put("timeStamp", String.valueOf(seconds));
				map.put("nonceStr", nonce_str);
				map.put("package", "prepay_id=" + prepay_id);
				map.put("signType", "MD5");
				map.put("paySign", paySign);
				map.put("outTradeNo", out_trade_no);
			} catch (Exception e) {
				log.info("插入失败！");
				ManageCaseBox manageCaseBox = manageCaseBoxMapper.selectByPrimaryKey(boxId);
				ManageCaseBox manageCaseBox1 = new ManageCaseBox();
				manageCaseBox1.setUseStatus((byte) 0);
				manageCaseBox1.setVersion(manageCaseBox.getVersion() + 1);
				ManageCaseBoxExample manageCaseBoxExample1 = new ManageCaseBoxExample();
				manageCaseBoxExample1.createCriteria().andVersionEqualTo(manageCaseBox.getVersion())
						.andIdEqualTo(manageCaseBox.getId());
				manageCaseBoxMapper.updateByExampleSelective(manageCaseBox1, manageCaseBoxExample1);

			}
		}
		return map;
	}



	/**
	 * 获取可用的柜子列表
	 * @param caseNo
	 * @return
	 */
	public List<ManageCaseBox> availableCabinet(String caseNo){

		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andCaseNoEqualTo(caseNo).andIsDelEqualTo((byte) 0)
				.andSwitchStatusEqualTo((byte) 1).andUseStatusEqualTo((byte) 0).andIsConnEqualTo((byte) 1);

		List<ManageCaseBox> selectByExample = manageCaseBoxMapper.selectByExample(example); //form manage_case_box where CASE_NO = and  SIZE = size and IS_DEL = 0 SWITCH_STATUS = 1 USE_STATUS = 0 IS_CONN = 1

//		List<Integer> collect = selectByExample.stream()
//				.collect(Collectors.mapping(ManageCaseBox::getDoorNum, Collectors.toList()));
		return selectByExample;
	}

	/**
	 * @author 刘成
	 * @since 2018年10月19日
	 * @param manageCaseBox 箱子信息
	 * @param openId 用户唯一标识
	 * @param type 表示 1存还是 2取还是 3清除等等操作
	 * @param source 来源 微信小程序还是支付宝小程序 等等
	 * @throws Exception
	 *             支付宝、微信、开箱取物逻辑（普通柜）
	 */
	@Override
	public void openMyCommonBoxByXcx(ManageCaseBox manageCaseBox, String openId, Byte type, Byte source)
			throws Exception {
		openMyCommonBoxByXcx(manageCaseBox,openId,type,source,BigDecimal.ZERO);
	}
	/**
	 * @author
	 * @since 2020年7月6日
	 * @param manageCaseBox 储物柜箱子信息
	 * @param openId 用户id
	 * @param type 类型  存 取 清除等等
	 * @param source 来源
	 * @param cost 入账费用 单位元
	 * @throws Exception
	 *  支付宝、微信、开箱取物逻辑（普通柜）
	 */
	@Override
	public void openMyCommonBoxByXcx(ManageCaseBox manageCaseBox, String openId, Byte type, Byte source,BigDecimal cost) throws Exception {
		
		Date saveTime = manageCaseBox.getSaveTime(); // 使用时间
		Integer doorNum = manageCaseBox.getDoorNum(); // 几号门
		String caseNo = manageCaseBox.getCaseNo(); // mac地址
		Date date = new Date();
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCreateTime(date);
		accessRecord.setType(type);
		accessRecord.setSource(source);
		accessRecord.setUserId(openId);
		accessRecord.setUseTime(date.getTime() - saveTime.getTime()); // 使用时长
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		if(cost.compareTo(BigDecimal.ZERO) == 1){
			accessRecord.setCharge(cost);//单位转换为元
		}
		// 开箱记录
		accessRecordMapper.insertSelective(accessRecord); // insert into access_record

		ManageCaseBox manageCaseBox1 = new ManageCaseBox();
		manageCaseBox.setPassword("0-0!!!");// 把密码改回为空
		manageCaseBox1.setUseStatus((byte) 0); // 使用状态改为空闲
		manageCaseBox1.setVersion(manageCaseBox.getVersion() + 1);  // 使用次数？
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andVersionEqualTo(manageCaseBox.getVersion()).andIdEqualTo(manageCaseBox.getId()); // VERSION = and  ID =
		// 修改箱子的状态
		int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(manageCaseBox1, example); // update manage_case_box
		if (updateByExampleSelective == 0) {
			throw new Exception();
		}

		// 开门操作 向消息队列发送了消息
		Connection connection = ConnectionUtils.getConnection(); // 获得了一个rabbitmq
		Channel channel = connection.createChannel();
		Map<String, Object> sendMap = new HashMap<>();
		sendMap.put("door", doorNum); // 几号门
		sendMap.put("timestamp", date.getTime());
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-message-ttl", 40000);
		channel.queueDeclare(caseNo, true, false, false, args); // 声明一个队列
		String writeValueAsString = mapper.writeValueAsString(sendMap);
		channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
		channel.close();
		connection.close();
		
	}

	@Override
	public void paySuccessByWx(ManageCaseBox manageCaseBox, Map<String, String> map1, String outTradeNo) {

		String caseNo = manageCaseBox.getCaseNo();
		ManageCaseExample caseExample = new ManageCaseExample();
		caseExample.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> selectByExample2 = manageCaseMapper.selectByExample(caseExample);
		ManageCase manageCase = selectByExample2.get(0);
		Integer compId = manageCase.getCompId();
		ManageComp manageComp = manageCompMapper.selectByPrimaryKey(compId);
		// 2.修改储物柜状态
		ManageCaseBox record = new ManageCaseBox();
		record.setId(manageCaseBox.getId());
		record.setUseStatus((byte) 0);
		manageCaseBoxMapper.updateByPrimaryKeySelective(record);
		// 3.修改支付订单状态

		String transactionId = map1.get("transaction_id");

		PayOrder payOrderRecord = new PayOrder();
		PayOrderExample payOrderExample = new PayOrderExample();
		payOrderRecord.setIsPay((byte) 1);
		payOrderRecord.setTransactionId(transactionId);
		payOrderExample.createCriteria().andOutTradeNoEqualTo(outTradeNo).andIsPayEqualTo((byte) 0);
		payOrderMapper.updateByExampleSelective(payOrderRecord, payOrderExample);

		// 4.插入取物记录
		String total_fee = map1.get("total_fee");
		Double valueOf = Double.valueOf(total_fee);
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCharge(new BigDecimal(valueOf).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP));
		accessRecord.setCreateTime(new Date());
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(new Date(), "yyyy-MM-dd"));
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.WX_XCX_SOURCE);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.GET_TYPE);
		accessRecord.setUserId(manageCaseBox.getUserId());
		accessRecord.setUseTime(new Date().getTime() - manageCaseBox.getSaveTime().getTime());
		accessRecordMapper.insertSelective(accessRecord);

		// 5.公司账户
		BigDecimal compBalance = manageComp.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double newTotalAmount = doubleValue + valueOf / 100;
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);

	}

	/**
	 * @author liuCheng
	 * @since 2018年11月7日 下午6:07:41
	 * @param map 微信回调请求过来的参数
	 * @param payOrder  订单信息
	 * @param manageCaseBox  箱子信息
	 *            普通柜付款成功后的逻辑
	 */
	@Override
	public void payCommonCaseWXFinish(Map<String, String> map, PayOrder payOrder, ManageCaseBox manageCaseBox) {
		// 查询储物柜
		String caseNo = manageCaseBox.getCaseNo();
		ManageCaseExample manageCaseExample = new ManageCaseExample();
		manageCaseExample.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> manageCaseList = manageCaseMapper.selectByExample(manageCaseExample); // 储物柜信息
		ManageCase manageCase = manageCaseList.get(0);
		Integer compId = manageCase.getCompId();

		// 查询公司
		ManageComp manageComp = manageCompMapper.selectByPrimaryKey(compId); // 储物柜所属公司信息

		Integer orderId = payOrder.getOrderId();
		// 金额
		String totalFee = map.get("total_fee");
		double valueOf = Double.valueOf(totalFee); // 交易的金额
		String transactionId = map.get("transaction_id"); // 订单号

		// 2.修改储物柜状态
		ManageCaseBox record = new ManageCaseBox();
		record.setId(manageCaseBox.getId());
		record.setUseStatus((byte) 0); //空闲状态
		record.setPassword("0-0!!!");
		manageCaseBoxMapper.updateByPrimaryKeySelective(record);

		// 3.修改支付订单状态
		PayOrder payOrderRecord = new PayOrder();
		payOrderRecord.setIsPay((byte) 1);
		payOrderRecord.setTransactionId(transactionId);
		payOrderRecord.setOrderId(orderId);
		payOrderMapper.updateByPrimaryKeySelective(payOrderRecord);

		// 4.插入取物记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCharge(new BigDecimal(valueOf).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP)); // 费用
		accessRecord.setCreateTime(new Date());
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(new Date(), "yyyy-MM-dd"));
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.WX_XCX_SOURCE);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.GET_TYPE);
		accessRecord.setUserId(manageCaseBox.getUserId()); // 取物的人
		accessRecord.setUseTime(new Date().getTime() - manageCaseBox.getSaveTime().getTime()); // 使用时长
		accessRecordMapper.insertSelective(accessRecord);

		// 5.公司账户
		BigDecimal compBalance = manageComp.getCompBalance(); // 公司账户余额
		double doubleValue = compBalance.doubleValue();
		double newTotalAmount = doubleValue + valueOf / 100; // 公司账户 加上 付款的金额
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);
	}

	/**
	 * @author liuCheng
	 * @since 2018年12月6日 下午4:44:55
	 * @param map
	 * @param payOrder
	 * @param manageCaseBox
	 *            预付金额完成的逻辑处理（微信）
	 * @throws Exception
	 */
	@Override
	public void prepayCommonCaseWXFinish(Map<String, String> map, PayOrder payOrder, ManageCaseBox manageCaseBox)
			throws Exception {
		log.info("预付订单处理。。。。");
		SysConstExample sysExample = new SysConstExample();
		sysExample.createCriteria().andNameEqualTo(WxConfig.ACCESS_TOKEN);
		List<SysConst> selectByExample = sysConstMapper.selectByExample(sysExample);
		String token = selectByExample.get(0).getValue();
		String prepayId = payOrder.getPrepayId();

		// 查询储物柜
		Date date = new Date();
		String caseNo = manageCaseBox.getCaseNo();
		Date saveTime = manageCaseBox.getSaveTime();
		Integer boxId = manageCaseBox.getId();
		ManageCaseExample manageCaseExample = new ManageCaseExample();
		manageCaseExample.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> manageCaseList = manageCaseMapper.selectByExample(manageCaseExample);
		ManageCase manageCase = manageCaseList.get(0);
		ManageCaseType caseType = manageCaseTypeMapper.selectByPrimaryKey(manageCase.getTypeId());
		Integer clearHour = Integer.parseInt(caseType.getUserTime());

		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.HOUR_OF_DAY, clearHour);
		Date endDate = calendar.getTime();
		Integer compId = manageCase.getCompId();
		String openId = payOrder.getOpenId();
		String outTradeNo = payOrder.getOutTradeNo();

		// 查询公司
		ManageComp manageComp = manageCompMapper.selectByPrimaryKey(compId);

		// 金额
		String totalFee = map.get("total_fee");
		double valueOf = Double.valueOf(payOrder.getTotalFee());// 这里应该为使用价格
		String transactionId = map.get("transaction_id");

		// 2.修改储物柜状态
		Integer version = manageCaseBox.getVersion();
		ManageCaseBox record = new ManageCaseBox();
		record.setUseStatus((byte) 1);
		record.setUserId(openId);
		record.setClearBoxTime(endDate);
		record.setVersion(version + 1);
		if (payOrder.getPassword() != null && !"".equals(payOrder.getPassword())) {
			record.setPassword(payOrder.getPassword());
		}
		ManageCaseBoxExample updateManageCaseBoxExample = new ManageCaseBoxExample();
		updateManageCaseBoxExample.createCriteria().andUserIdEqualTo("123").andUseStatusEqualTo((byte) 1)
				.andVersionEqualTo(version).andIdEqualTo(manageCaseBox.getId());
		int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(record, updateManageCaseBoxExample);

		// 3.修改支付订单状态
		Integer orderId = payOrder.getOrderId();
		PayOrder payOrderRecord = new PayOrder();
		payOrderRecord.setIsPay((byte) 1);
		payOrderRecord.setTransactionId(transactionId);
		payOrderRecord.setOrderId(orderId);
		int updateByPrimaryKeySelective2 = payOrderMapper.updateByPrimaryKeySelective(payOrderRecord);

		// 4.删除预付订单的记录
		PrepayOrderExample prepayOrderExample = new PrepayOrderExample();
		prepayOrderExample.createCriteria().andOutTradeNoEqualTo(outTradeNo);
		prepayOrderMapper.deleteByExample(prepayOrderExample);

		// 5.插入存物记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCharge(new BigDecimal(valueOf).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP));
		accessRecord.setCreateTime(date);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(new Date(), "yyyy-MM-dd"));
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.WX_XCX_SOURCE);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.SAVE_TYEP);
		accessRecord.setUserId(openId);
		accessRecordMapper.insertSelective(accessRecord);

		// 添加押金
		if (payOrder.getPayPledge() != null) {
			CustomersAmountExample example = new CustomersAmountExample();
			example.createCriteria().andOpenIdEqualTo(payOrder.getOpenId());
			List<CustomersAmount> list = customersAmountMapper.selectByExample(example);
			if (!list.isEmpty()) {
				CustomersAmount ca = list.get(0);
				ca.setIsPay((byte) 1);
				ca.setSource((byte) 2);
				ca.setTotalPledge(new BigDecimal(totalFee));// 总金额
				ca.setAssureAmount(payOrder.getPayPledge());
				ca.setAssureTransactionId(transactionId);
				customersAmountMapper.updateByPrimaryKey(ca);
			}
		}

		// 6.公司账户
		BigDecimal compBalance = manageComp.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double newTotalAmount = doubleValue + valueOf / 100;
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		int updateByPrimaryKeySelective3 = manageCompMapper.updateByPrimaryKeySelective(compRecord);
		//log.info("异常: "+updateByExampleSelective+"  "+updateByPrimaryKeySelective2+" "+updateByPrimaryKeySelective3);
		if (updateByExampleSelective == 0 || updateByPrimaryKeySelective2 == 0 || updateByPrimaryKeySelective3 == 0) {
			throw new Exception();

		}
		// 7.开门
		log.info("开门。。。。。caseNo:" + caseNo + " door:" + manageCaseBox.getDoorNum());
		Connection connection = ConnectionUtils.getConnection();
		Channel channel = connection.createChannel();
		Map<String, Object> sendMap = new HashMap<>();
		sendMap.put("door", manageCaseBox.getDoorNum());
		sendMap.put("timestamp", new Date().getTime());
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-message-ttl", 40000);
		channel.queueDeclare(caseNo, true, false, false, args);
		String writeValueAsString = mapper.writeValueAsString(sendMap);
		channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
		channel.close();
		connection.close();

		String name = "储物柜租用成功";
		// 8.发送模板消息
		String page = "pages/useBox/useBox?boxId=" + boxId;
		Integer code = SendXcxMessageUtil.sendWxMessage(name, saveTime, endDate, token, prepayId, openId, page);
		if (code.equals(40001) || code.equals(42001)) {
			String newToken = sysConstService.updateAccessTokenByWXXcx();
			SendXcxMessageUtil.sendWxMessage(name, saveTime, endDate, newToken, prepayId, openId, page);
		}
	}

	/**
	 * @author liuCheng
	 * @since 2018年12月13日 下午3:15:32
	 * @param payOrder
	 *            支付宝预付成功后的处理逻辑
	 * @throws Exception
	 * @throws Exception
	 * @throws Exception
	 */
	@Override
	public void prepaySucessToOpen(PayOrder payOrder) throws Exception {
		log.info("支付成功异步处理逻辑。。。。");
		Date date = new Date();
		String openId = payOrder.getOpenId();
		Integer boxId = payOrder.getBoxId();
		String outTradeNo = payOrder.getOutTradeNo();
		String transactionId = payOrder.getTransactionId();
		// 查询箱门的信息
		ManageCaseBox manageCaseBox = manageCaseBoxMapper.selectByPrimaryKey(boxId);
		// 查询储物柜
		String caseNo = manageCaseBox.getCaseNo();
		Date saveTime = manageCaseBox.getSaveTime();
		ManageCaseExample selectManageCaseExample = new ManageCaseExample();
		selectManageCaseExample.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> manageCaseList = manageCaseMapper.selectByExample(selectManageCaseExample);
		ManageCase manageCase = manageCaseList.get(0);

		ManageCaseType caseType = manageCaseTypeMapper.selectByPrimaryKey(manageCase.getTypeId());
		Integer clearHour = Integer.parseInt(caseType.getUserTime());
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.HOUR_OF_DAY, clearHour);
		Date endDate = calendar.getTime();
		// 查询公司
		Integer compId = manageCase.getCompId();
		ManageComp manageComp = manageCompMapper.selectByPrimaryKey(compId);
		// 金额
		Integer totalFee = payOrder.getTotalFee();// 单位分
		// 2.修改储物柜状态
		Integer version = manageCaseBox.getVersion();
		ManageCaseBox updateManageCaseBoxRecord = new ManageCaseBox();
		if (payOrder.getPassword() != null && !"".equals(payOrder.getPassword())) {
			updateManageCaseBoxRecord.setPassword(payOrder.getPassword());// 把密码放在caseBox里面。
		}
		updateManageCaseBoxRecord.setUserId(openId);
		updateManageCaseBoxRecord.setVersion(version + 1);
		updateManageCaseBoxRecord.setClearBoxTime(endDate);
		updateManageCaseBoxRecord.setSaveSource(AllConst.CASE_BOX_SAVE_SOURCE.ALI_XCX_SAVE_SOURCE);
		ManageCaseBoxExample updateManageCaseBoxExample = new ManageCaseBoxExample();
		updateManageCaseBoxExample.createCriteria().andVersionEqualTo(version).andIdEqualTo(boxId)
				.andUserIdEqualTo("123").andUseStatusEqualTo((byte) 1);
		int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(updateManageCaseBoxRecord,
				updateManageCaseBoxExample);
		if (updateByExampleSelective == 0) {
			throw new Exception();
		}
		// 3.修改支付订单状态
		Integer orderId = payOrder.getOrderId();
		PayOrder record = new PayOrder();
		record.setIsPay((byte) 1);
		record.setOrderId(orderId);
		payOrderMapper.updateByPrimaryKeySelective(record);

		// 押金存入customersAmount表中
		BigDecimal cashPledge = payOrder.getPayPledge();
		if (cashPledge.compareTo(BigDecimal.ZERO) == 1) {
			CustomersAmountExample example = new CustomersAmountExample();
			example.createCriteria().andOpenIdEqualTo(openId);
			List<CustomersAmount> list = customersAmountMapper.selectByExample(example);
			if (!list.isEmpty()) {
				CustomersAmount customersAmount = list.get(0);
				customersAmount.setAssureAmount(cashPledge);
				// customersAmount.setTotalPledge(totalPledge);
				customersAmount.setIsPay((byte) 1);
				customersAmount.setSource((byte) 3);// 来源支付宝
				customersAmount.setAssureTransactionId(payOrder.getTransactionId());// 订单号
				customersAmountMapper.updateByPrimaryKey(customersAmount);
			}
		}

		// 4.删除预付订单的记录
		PrepayOrderExample deletePrepayOrderExample = new PrepayOrderExample();
		deletePrepayOrderExample.createCriteria().andOutTradeNoEqualTo(outTradeNo);
		prepayOrderMapper.deleteByExample(deletePrepayOrderExample);
		// 5.插入存物记录
		double money = new BigDecimal(totalFee).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP).doubleValue();
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(boxId);
		accessRecord.setCharge(BigDecimal.valueOf(money));
		accessRecord.setCreateTime(date);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.ALI_XCX_SOURCE);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.SAVE_TYEP);
		accessRecord.setUserId(openId);
		accessRecordMapper.insertSelective(accessRecord);

		// 6.公司账户
		BigDecimal compBalance = manageComp.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double newTotalAmount = doubleValue + money;
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);

		// 7.开门
		Integer doorNum = manageCaseBox.getDoorNum();
		Connection connection = ConnectionUtils.getConnection();
		Channel channel = connection.createChannel();
		Map<String, Object> sendMap = new HashMap<>();
		sendMap.put("door", doorNum);
		sendMap.put("timestamp", new Date().getTime());
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-message-ttl", 40000);
		channel.queueDeclare(caseNo, true, false, false, args);
		String writeValueAsString = mapper.writeValueAsString(sendMap);
		channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
		channel.close();
		connection.close();
		// 8.发送支付成功消息
		String page = "pages/useBox/useBox?boxId=" + boxId;
		SendXcxMessageUtil.sendMessageToAli(transactionId, openId, saveTime, "储物柜租用成功", endDate, page);
	}

	@Override
	public void boxClearBatch(List<ManageCaseBox> manageCaseBoxList, ManageCase manageCase,
			ManageCaseType manageCaseType) throws Exception {

		List<Integer> boxIdList = manageCaseBoxList.stream()
				.collect(Collectors.mapping(ManageCaseBox::getId, Collectors.toList()));

		Date date = new Date();
		String dateStr = DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd");

		ManageUser user = UserContext.getUser();
		String loginName = user.getLoginName();

		List<AccessRecord> userAccessRecordList = new ArrayList<>();
		List<CustomersAmount> customersAmountList = new ArrayList<>();
		manageCaseBoxList.forEach(a -> {
			Date saveTime = a.getSaveTime();
			long time = date.getTime() - saveTime.getTime();
			// 计算金额
			double amount = CustomersAmountCount.getAliCharge(a, manageCase, manageCaseType);
			if (amount > 0) {
				// 添加
				amount = amount > 100 ? 100 : amount;
				CustomersAmount customersAmount = new CustomersAmount();
				customersAmount.setOpenId(a.getUserId());
				customersAmount.setTotalAmount(BigDecimal.valueOf(amount));
				customersAmountList.add(customersAmount);
			}
			Byte source = a.getSaveSource();
			// 插入使用记录

			AccessRecord accessRecord = SavaSourceToRecordSource.savaSourceToRecordSource(source);
			accessRecord.setUserId(a.getUserId());
			accessRecord.setBoxId(a.getId());
			accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.PASSIVITY_CLEAR_TYEP);
			accessRecord.setCreateTime(date);
			accessRecord.setCreateDay(dateStr);
			accessRecord.setCharge(BigDecimal.valueOf(0 - amount));
			accessRecord.setUseTime(time);
			userAccessRecordList.add(accessRecord);
		});
		// 1.插入用户的使用记录
		List<AccessRecord> list = new ArrayList<>();
		boxIdList.forEach(a -> {
			AccessRecord accessRecord = new AccessRecord();
			accessRecord.setSource((byte) 1);
			accessRecord.setBoxId(a);
			accessRecord.setCreateTime(date);
			accessRecord.setType((byte) 3);
			accessRecord.setUserId(loginName);
			accessRecord.setCreateDay(dateStr);
			accessRecord.setCharge(BigDecimal.valueOf(0));
			accessRecord.setUseTime(0L);
			list.add(accessRecord);
		});
		int insertBatch = 1;
		if (list.size() > 0) {
			insertBatch = accessRecordMapper.insertBatch(list);
		}
		int updateByExampleSelective = 1;
		if (boxIdList.size() > 0) {
			ManageCaseBox manageCaseBoxRecord = new ManageCaseBox();
			manageCaseBoxRecord.setUseStatus((byte) 0);
			ManageCaseBoxExample example = new ManageCaseBoxExample();
			example.createCriteria().andIdIn(boxIdList);
			// 2.修改状态
			updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(manageCaseBoxRecord, example);
		}
		if (customersAmountList.size() > 0) {
			customersAmountMapper.updateUserAmount(customersAmountList);
		}
		int insertBatch2 = 1;
		if (userAccessRecordList.size() > 0) {
			insertBatch2 = accessRecordMapper.insertBatch(userAccessRecordList);
		}
		// 3.插入清除记录
		// 修改用户的资金账户
		if (insertBatch == 0 || updateByExampleSelective == 0 || insertBatch2 == 0) {
			throw new Exception();
		}
	}

	/**
	 * @author liuCheng
	 * @since 2018年12月19日 上午9:34:33
	 * @param time
	 * @param payTime
	 * @param payType
	 * @param price
	 * @param priceSize
	 * @param isSize
	 * @param userTime
	 * @param size
	 * @return 计算金额
	 */

	/**
	 * @author liuCheng
	 * @since 2018年12月19日 下午1:18:56
	 * @param boxIdList
	 *            快递柜批量清柜
	 * @throws Exception
	 */
	@Override
	public void clearBoxByExpress(List<Integer> boxIdList, String loginName) throws Exception {
		Date date = new Date();
		String dateStr = DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd");
		// 清除储物柜状态
		ManageCaseBox updateRecord = new ManageCaseBox();
		ManageCaseBoxExample updateExample = new ManageCaseBoxExample();
		updateRecord.setUseStatus((byte) 0);
		updateExample.createCriteria().andIdIn(boxIdList);
		int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(updateRecord, updateExample);
		// 插入清除记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setSource((byte) 1);
		accessRecord.setCreateTime(date);
		accessRecord.setType((byte) 3);
		accessRecord.setUserId(loginName);
		accessRecord.setCreateDay(dateStr);
		int insertBatchByExpress = accessRecordMapper.insertBatchByExpress(accessRecord, boxIdList);

		// 修改短信的状态码
		MobileKey updateMobileKeyRecord = new MobileKey();
		MobileKeyExample updateMobileKeyExample = new MobileKeyExample();
		updateMobileKeyRecord.setStatus((byte) 2);
		updateMobileKeyExample.createCriteria().andStatusEqualTo((byte) 1).andBoxIdIn(boxIdList);
		int updateByExampleSelective2 = mobileKeyMapper.updateByExampleSelective(updateMobileKeyRecord,
				updateMobileKeyExample);
		if (updateByExampleSelective == 0 || insertBatchByExpress == 0 || updateByExampleSelective2 == 0) {
			throw new Exception();
		}

	}

	/**
	 * @author liuCheng
	 * @since 2018年12月21日 上午10:09:41
	 * @param map
	 * @param payOrder
	 * @param manageCaseBox
	 */
	@Override
	public void payMidWayCommonCaseWXFinish(Map<String, String> map, PayOrder payOrder, ManageCaseBox manageCaseBox) {
		Date date = new Date();

		// 查询储物柜
		String caseNo = manageCaseBox.getCaseNo();
		ManageCaseExample manageCaseExample = new ManageCaseExample();
		manageCaseExample.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> manageCaseList = manageCaseMapper.selectByExample(manageCaseExample);
		ManageCase manageCase = manageCaseList.get(0);
		Integer compId = manageCase.getCompId();
		Integer clearHour = manageCase.getClearHour();
		Calendar instance = Calendar.getInstance();
		instance.add(Calendar.HOUR_OF_DAY, clearHour);

		// 查询公司
		ManageComp manageComp = manageCompMapper.selectByPrimaryKey(compId);

		Integer orderId = payOrder.getOrderId();
		// 金额
		String totalFee = map.get("total_fee");
		double valueOf = Double.valueOf(totalFee);
		String transactionId = map.get("transaction_id");

		// 2.修改储物柜的储物时间
		ManageCaseBox record = new ManageCaseBox();
		record.setId(manageCaseBox.getId());
		record.setSaveTime(date);
		// record.setPassword("0-0!!!");
		record.setIsHalfwayOpen((byte) 1);// 设置为中途取过物品
		record.setClearBoxTime(instance.getTime());
		manageCaseBoxMapper.updateByPrimaryKeySelective(record);

		// 3.修改支付订单状态
		PayOrder payOrderRecord = new PayOrder();
		payOrderRecord.setIsPay((byte) 1);
		payOrderRecord.setTransactionId(transactionId);
		payOrderRecord.setOrderId(orderId);
		payOrderMapper.updateByPrimaryKeySelective(payOrderRecord);

		// 4.插入取物记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCharge(new BigDecimal(valueOf).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP));
		accessRecord.setCreateTime(new Date());
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(new Date(), "yyyy-MM-dd"));
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.WX_XCX_SOURCE);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.MIDWAY_GET_TYPE);
		accessRecord.setUserId(manageCaseBox.getUserId());
		accessRecord.setUseTime(new Date().getTime() - manageCaseBox.getSaveTime().getTime());
		accessRecordMapper.insertSelective(accessRecord);

		// 5.公司账户
		BigDecimal compBalance = manageComp.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double newTotalAmount = doubleValue + valueOf / 100;
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);

	}

	@Override
	public void openMidWayMyCommonBoxByXcx(ManageCaseBox manageCaseBox, String openId, Byte type, Byte source)
			throws Exception {

		Date saveTime = manageCaseBox.getSaveTime();
		Integer doorNum = manageCaseBox.getDoorNum();
		String caseNo = manageCaseBox.getCaseNo();
		Date date = new Date();
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCreateTime(date);
		accessRecord.setType(type);
		accessRecord.setSource(source);
		accessRecord.setUserId(openId);
		accessRecord.setUseTime(date.getTime() - saveTime.getTime());
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecordMapper.insertSelective(accessRecord);
		//
		ManageCaseBox manageCaseBox1 = new ManageCaseBox();
		manageCaseBox1.setSaveTime(date);
		manageCaseBox1.setVersion(manageCaseBox.getVersion() + 1);
		manageCaseBox1.setIsHalfwayOpen((byte) 1);// 设置为中途取过物品
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andVersionEqualTo(manageCaseBox.getVersion()).andIdEqualTo(manageCaseBox.getId());
		int updateByExampleSelective = manageCaseBoxMapper.updateByExampleSelective(manageCaseBox1, example);
		if (updateByExampleSelective == 0) {
			throw new Exception();
		}
		// 开门
		Connection connection = ConnectionUtils.getConnection();
		Channel channel = connection.createChannel();
		Map<String, Object> sendMap = new HashMap<>();
		sendMap.put("door", doorNum);
		sendMap.put("timestamp", date.getTime());
		ObjectMapper mapper = new ObjectMapper();
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-message-ttl", 40000);
		channel.queueDeclare(caseNo, true, false, false, args);
		String writeValueAsString = mapper.writeValueAsString(sendMap);
		channel.basicPublish("", caseNo, null, writeValueAsString.getBytes());
		channel.close();
		connection.close();
	}

	/**
	 * @author liuCheng
	 * @since 2018年12月21日 下午4:39:41
	 * @param payOrder
	 * @param manageCaseBox
	 * @param manageCase
	 * @param time
	 *            中途取物
	 */
	@Override
	public void payFinishByAliAndCommonBoxMidWay(PayOrder payOrder, ManageCaseBox manageCaseBox, ManageCase manageCase,
			Long time) {
		Date date = new Date();
		Integer compId = manageCase.getCompId();
		Integer clearHour = manageCase.getClearHour();
		Calendar instance = Calendar.getInstance();
		instance.add(Calendar.HOUR_OF_DAY, clearHour);

		ManageComp selectByPrimaryKey = manageCompMapper.selectByPrimaryKey(compId);
		Integer id = manageCaseBox.getId();
		Integer totalFee = payOrder.getTotalFee();
		BigDecimal compBalance = selectByPrimaryKey.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double money = new BigDecimal(totalFee).divide(new BigDecimal(100), 3, BigDecimal.ROUND_HALF_UP).doubleValue();
		double newTotalAmount = doubleValue + money;

		// 2.修改订单状态
		PayOrder record = new PayOrder();
		record.setIsPay((byte) 1);
		record.setOrderId(payOrder.getOrderId());
		payOrderMapper.updateByPrimaryKeySelective(record);
		// 3.插入记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(id);
		accessRecord.setCharge(BigDecimal.valueOf(money));
		accessRecord.setCreateTime(date);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd"));
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.ALI_XCX_SOURCE);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.MIDWAY_GET_TYPE);
		accessRecord.setUserId(manageCaseBox.getUserId());
		accessRecord.setUseTime(time);
		accessRecordMapper.insertSelective(accessRecord);

		// 4.修改储物柜状态
		ManageCaseBox caseBoxRecord = new ManageCaseBox();
		caseBoxRecord.setId(id);
		caseBoxRecord.setIsHalfwayOpen((byte) 1);
		// caseBoxRecord.setPassword("0-0!!!");
		caseBoxRecord.setSaveTime(date);
		caseBoxRecord.setClearBoxTime(instance.getTime());
		manageCaseBoxMapper.updateByPrimaryKeySelective(caseBoxRecord);

		// 5.转账或修改公司账户信息
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);
	}

	// @Override
	// public void clearByOneself(ManageCaseBox manageCaseBox, ManageCase
	// manageCase, ManageCaseType manageCaseType,
	// Byte source, Byte type) throws Exception {
	//
	// Date date = new Date();
	// String dateStr = DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd");
	//
	// Integer version = manageCaseBox.getVersion();
	// Date saveTime = manageCaseBox.getSaveTime();
	// Long useTime = date.getTime() - saveTime.getTime();
	// String openId = manageCaseBox.getUserId();
	// Integer boxId = manageCaseBox.getId();
	//
	// // 计算金额
	// double aliCharge = CustomersAmountCount.getAliCharge(manageCaseBox,
	// manageCase, manageCaseType);
	// aliCharge = aliCharge > 100 ? 100 : aliCharge;
	// // 修改账户余额
	// CustomersAmount customersAmount = new CustomersAmount();
	// customersAmount.setOpenId(openId);
	// customersAmount.setTotalAmount(BigDecimal.valueOf(aliCharge));
	// customersAmountMapper.updateUserAmountOne(customersAmount);
	//
	// // 清除状态
	// ManageCaseBoxExample updateExample = new ManageCaseBoxExample();
	// updateExample.createCriteria().andVersionEqualTo(version).andIdEqualTo(boxId);
	// ManageCaseBox record = new ManageCaseBox();
	// record.setUseStatus((byte) 0);
	// record.setPassword(null);
	// record.setVersion(version + 1);
	// manageCaseBoxMapper.updateByExampleSelective(record, updateExample);
	// // 插入清除记录
	// AccessRecord accessRecord = new AccessRecord();
	// accessRecord.setBoxId(boxId);
	// accessRecord.setCreateDay(dateStr);
	// accessRecord.setCreateTime(date);
	// accessRecord.setSource(source);
	// accessRecord.setType(type);
	// accessRecord.setUserId(openId);
	// accessRecord.setUseTime(useTime);
	// accessRecord.setCharge(BigDecimal.valueOf(-aliCharge));
	// accessRecordMapper.insertSelective(accessRecord);
	// }

	@Override
	public void clearByOneself(ManageCaseBox manageCaseBox, ManageCase manageCase, ManageCaseType manageCaseType,
			Byte source, Byte type) throws Exception {
		clearByOneself(manageCaseBox,manageCase,manageCaseType,source,type,BigDecimal.ZERO);
	}
	/**
	 * @param manageCaseBox 储物柜柜门
	 * @param manageCase 储物柜
	 * @param manageCaseType 收费类型
	 * @param source 来源
	 * @param type 类型
	 * @param cost 入公司账单费用 单位元
	 */
	@Override
	public void clearByOneself(ManageCaseBox manageCaseBox, ManageCase manageCase, ManageCaseType manageCaseType,
			Byte source, Byte type, BigDecimal cost) throws Exception {
		Date date = new Date();
		String dateStr = DateTimeHelper.formatDateTimetoString(date, "yyyy-MM-dd");

		Integer version = manageCaseBox.getVersion();
		Date saveTime = manageCaseBox.getSaveTime();
		Long useTime = date.getTime() - saveTime.getTime();
		String openId = manageCaseBox.getUserId();
		Integer boxId = manageCaseBox.getId();

//		// 修改账户余额
//		CustomersAmount customersAmount = new CustomersAmount();
//		customersAmount.setOpenId(openId);
//		customersAmount.setTotalAmount(BigDecimal.ZERO);
//		customersAmount.setAssureAmount(BigDecimal.ZERO);
//		customersAmount.setIsPay((byte) 0);
//		customersAmountMapper.updateUserAmountOne(customersAmount);

		// 清除状态
		ManageCaseBoxExample updateExample = new ManageCaseBoxExample();
		updateExample.createCriteria().andVersionEqualTo(version).andIdEqualTo(boxId);
		ManageCaseBox record = new ManageCaseBox();
		record.setUseStatus((byte) 0);
		record.setPassword("0-0!!!");
		record.setIsHalfwayOpen((byte) 0);
		record.setVersion(version + 1);
		manageCaseBoxMapper.updateByExampleSelective(record, updateExample);
		// 插入清除记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(boxId);
		accessRecord.setCreateDay(dateStr);
		accessRecord.setCreateTime(date);
		accessRecord.setSource(source);
		accessRecord.setType(type);
		accessRecord.setUserId(openId);
		accessRecord.setUseTime(useTime);
		if(cost.compareTo(BigDecimal.ZERO) == 1){
			accessRecord.setCharge(cost);//单位为元
		}
		accessRecordMapper.insertSelective(accessRecord);
		
	}


	/**
	 * @author liuCheng
	 * @since 2019年1月4日 上午11:09:57
	 * @param
	 * @param payOrder
	 * @param manageCaseBox
	 *            续费使用的逻辑处理
	 * @throws Exception
	 */
	@Override
	public void continueCommonCaseFinish(String transactionId, BigDecimal amount, PayOrder payOrder,
			ManageCaseBox manageCaseBox, Byte source) throws Exception {
		// 查询储物柜
		Date date = new Date();
		Date saveTime = manageCaseBox.getSaveTime();
		String caseNo = manageCaseBox.getCaseNo();
		Integer boxId = manageCaseBox.getId();
		ManageCaseExample manageCaseExample = new ManageCaseExample();
		manageCaseExample.createCriteria().andCaseNoEqualTo(caseNo);
		List<ManageCase> manageCaseList = manageCaseMapper.selectByExample(manageCaseExample);
		ManageCase manageCase = manageCaseList.get(0);
		ManageCaseType caseType = manageCaseTypeMapper.selectByPrimaryKey(manageCase.getTypeId());
		Integer clearHour = Integer.parseInt(caseType.getUserTime());

		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.HOUR_OF_DAY, clearHour);
		Date endDate = calendar.getTime();
		Integer compId = manageCase.getCompId();
		String openId = payOrder.getOpenId();

		// 查询公司
		ManageComp manageComp = manageCompMapper.selectByPrimaryKey(compId);

		// 2.修改储物柜状态
		ManageCaseBox record = new ManageCaseBox();
		record.setClearBoxTime(calendar.getTime());
		record.setId(boxId);
		record.setSaveTime(date);
		manageCaseBoxMapper.updateByPrimaryKeySelective(record);

		// 3.修改支付订单状态
		Integer orderId = payOrder.getOrderId();
		PayOrder payOrderRecord = new PayOrder();
		payOrderRecord.setIsPay((byte) 1);
		payOrderRecord.setTransactionId(transactionId);
		payOrderRecord.setOrderId(orderId);
		payOrderMapper.updateByPrimaryKeySelective(payOrderRecord);

		// 4.插入继续使用的记录
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(manageCaseBox.getId());
		accessRecord.setCharge(amount);
		accessRecord.setCreateTime(date);
		accessRecord.setCreateDay(DateTimeHelper.formatDateTimetoString(new Date(), "yyyy-MM-dd"));
		accessRecord.setSource(source);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.CONTINUE_USE);
		accessRecord.setUserId(openId);
		accessRecordMapper.insertSelective(accessRecord);

		// 6.公司账户
		BigDecimal compBalance = manageComp.getCompBalance();
		double doubleValue = compBalance.doubleValue();
		double newTotalAmount = doubleValue + amount.doubleValue();
		ManageComp compRecord = new ManageComp();
		compRecord.setCompId(manageCase.getCompId());
		compRecord.setCompBalance(BigDecimal.valueOf(newTotalAmount));
		manageCompMapper.updateByPrimaryKeySelective(compRecord);

		String name = "储物柜续费成功";
		if (source.equals(AllConst.ACCESS_RECORD_SOURCE.ALI_XCX_SOURCE)) {// 支付宝
			String page = "pages/useBox/useBox?boxId=" + boxId;
			SendXcxMessageUtil.sendMessageToAli(transactionId, openId, saveTime, name, endDate, page);
		} else {
			String prepayId = payOrder.getPrepayId();
			SysConstExample sysExample = new SysConstExample();
			sysExample.createCriteria().andNameEqualTo(WxConfig.ACCESS_TOKEN);
			List<SysConst> selectByExample = sysConstMapper.selectByExample(sysExample);
			String token = selectByExample.get(0).getValue();
			String page = "pages/useBox/useBox?boxId=" + boxId;
			Integer code = SendXcxMessageUtil.sendWxMessage(name, saveTime, endDate, token, prepayId, openId, page);
			if (code.equals(40001) || code.equals(42001)) {
				String newToken = sysConstService.updateAccessTokenByWXXcx();
				SendXcxMessageUtil.sendWxMessage(name, saveTime, endDate, newToken, prepayId, openId, page);
			}
		}

	}

	/**
	 * @author liuCheng
	 * @since 2019年1月21日 上午11:21:33
	 * @param manageCaseBox
	 */
	@Override
	public void clearBoxToSwim(ManageCaseBox manageCaseBox) {
		Date date = new Date();
		String dateStr = DateTimeHelper.formatDateTimetoString(date, DateTimeHelper.FMT_yyyyMMdd);
		Integer boxId = manageCaseBox.getId();
		String userId = manageCaseBox.getUserId();
		Date saveTime = manageCaseBox.getSaveTime();
		ManageCaseBox record = new ManageCaseBox();
		record.setUseStatus((byte) 0);
		record.setId(boxId);
		manageCaseBoxMapper.updateByPrimaryKeySelective(record);
		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(boxId);
		accessRecord.setCreateTime(new Date());
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.SWIMING_SOURCE);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.CLEAR_TYEP);
		accessRecord.setUserId(userId);
		accessRecord.setCreateDay(dateStr);
		accessRecord.setUseTime(date.getTime() - saveTime.getTime());
		accessRecordMapper.insertSelective(accessRecord);

	}

	/**
	 * @author liuCheng
	 * @since 2019年1月21日 上午11:45:32
	 * @param manageCaseBox
	 */
	@Override
	public void saveToSwim(ManageCaseBox manageCaseBox) {
		Integer boxId = manageCaseBox.getId();
		Integer version = manageCaseBox.getVersion();
		ManageCaseBox record = new ManageCaseBox();
		record.setId(boxId);
		record.setSaveTime(new Date());
		record.setUseStatus((byte) 1);
		record.setVersion(version + 1);
		record.setSaveSource(AllConst.ACCESS_RECORD_SOURCE.SWIMING_SOURCE);
		ManageCaseBoxExample manageCaseBoxExample = new ManageCaseBoxExample();
		manageCaseBoxExample.createCriteria().andIdEqualTo(boxId).andVersionEqualTo(version);
		manageCaseBoxMapper.updateByExampleSelective(record, manageCaseBoxExample);
	}

	@Override
	public void clearBoxToSwimToCase(Integer boxId, Date date) {
		String dateStr = DateTimeHelper.formatDateTimetoString(date, DateTimeHelper.FMT_yyyyMMdd);
		// 清除
		ManageCaseBox record = new ManageCaseBox();
		record.setId(boxId);
		record.setUseStatus((byte) 0);
		manageCaseBoxMapper.updateByPrimaryKeySelective(record);
		AccessRecord record2 = new AccessRecord();
		// 插入清除记录
		record2.setBoxId(boxId);
		record2.setCreateDay(dateStr);
		record2.setCreateTime(date);
		record2.setSource(AllConst.ACCESS_RECORD_SOURCE.ADMIN_SOURCE);
		record2.setType(AllConst.ACCESS_RECORD_TYPE.CLEAR_TYEP);
		record2.setUserId("柜体操作");
		accessRecordMapper.insertSelective(record2);

	}

	@Override
	public void clearBoxToSwimToCaseBatch(String mac, Date date) {
		String dateStr = DateTimeHelper.formatDateTimetoString(date, DateTimeHelper.FMT_yyyyMMdd);
		ManageCaseBoxExample manageCaseBoxExample = new ManageCaseBoxExample();
		manageCaseBoxExample.createCriteria().andCaseNoEqualTo(mac).andIsDelEqualTo((byte) 0);
		List<ManageCaseBox> manageCaseBoxList = manageCaseBoxMapper.selectByExample(manageCaseBoxExample);
		List<Integer> boxIdList = manageCaseBoxList.stream()
				.collect(Collectors.mapping(ManageCaseBox::getId, Collectors.toList()));
		ManageCaseBox manageCaseBoxRecord = new ManageCaseBox();
		manageCaseBoxRecord.setUseStatus((byte) 0);
		ManageCaseBoxExample example = new ManageCaseBoxExample();
		example.createCriteria().andIdIn(boxIdList);
		manageCaseBoxMapper.updateByExampleSelective(manageCaseBoxRecord, example);

		List<AccessRecord> list = new ArrayList<AccessRecord>();
		manageCaseBoxList.forEach(a -> {
			AccessRecord record = new AccessRecord();
			record.setBoxId(a.getId());
			record.setCreateDay(dateStr);
			record.setCreateTime(date);
			record.setSource(AllConst.ACCESS_RECORD_SOURCE.ADMIN_SOURCE);
			record.setType(AllConst.ACCESS_RECORD_TYPE.CLEAR_TYEP);
			record.setUserId("柜体操作");
			record.setCharge(BigDecimal.valueOf(0));
			record.setUseTime(0l);
			list.add(record);
		});
		accessRecordMapper.insertBatch(list);

	}

	@Override
	public void clearBoxByOut(ManageCaseBox manageCaseBox) {
		Integer boxId = manageCaseBox.getId();
		ManageCaseBox record = new ManageCaseBox();
		record.setId(boxId);
		record.setUseStatus((byte) 0);
		manageCaseBoxMapper.updateByPrimaryKeySelective(record);
		Date date = new Date();
		String dateStr = DateTimeHelper.formatDateTimetoString(date, DateTimeHelper.FMT_yyyyMMdd);

		AccessRecord accessRecord = new AccessRecord();
		accessRecord.setBoxId(boxId);
		accessRecord.setCreateDay(dateStr);
		accessRecord.setCreateTime(date);
		accessRecord.setSource(AllConst.ACCESS_RECORD_SOURCE.SWIMING_SOURCE);
		accessRecord.setType(AllConst.ACCESS_RECORD_TYPE.CLEAR_TYEP);
		accessRecord.setUserId(manageCaseBox.getUserId());
		accessRecord.setUseTime(date.getTime() - manageCaseBox.getSaveTime().getTime());
		accessRecordMapper.insertSelective(accessRecord);
	}

}
